【问题标题】:a few questions for x86 assembly: AccessViolationException, pointer arithmetic, and string comparisonx86 汇编的几个问题:AccessViolationException、指针算术和字符串比较
【发布时间】:2015-10-19 11:57:22
【问题描述】:

在我提出任何问题之前,我知道最好的建议是学习如何使用调试器,唯一的问题是我不确定如何让它在我的 mac 上的虚拟机中的 Visual Studio 2013 上运行。我和我的教授都在努力让它运行,所以目前调试不是我的选择。

程序规范: int l_search (char* list, int count, char* token)

list - 要搜索的结构列表的起始地址。结构包含一个学生 ID 的 int,后跟一个由 20 个元素组成的 char 数组作为学生姓名

count - 列表中名称的总数

token - 要搜索或在列表中的名称

该函数返回列表中学生记录的学生ID。在构建列表时,ID 按从 1) 开始的顺序填充。如果找不到该名称,则返回 0。返回 0 时,在控制台上打印一条消息。没有部分搜索,必须全有或全无。

所以这是我在汇编中的尝试:

xor eax, eax                        ; zero out the `enter code here`result, eax
xor ebx, ebx                        ; zero out a counter, ebx
xor edx, edx                        ; zero out a token modifier, edx
mov esi, list                       ; move the list pointer to esi
mov edi, token                      ; move the token pointer to edi
mov dl, BYTE PTR[edi]               ; move the first char to dl

LOWERCASE_TOKEN :

or dl, 0x20                         ; lowercase the char
mov BYTE PTR[edi], dl               ; set the char in token to lowercase
//mov BYTE PTR[edi + ebx], dl       ;
add ebx, 1                          ; increment counter
add edi, 1                          ; move token pointer to the next char
//mov dl, BYTE PTR[edi + ebx]       ; set the next char to dl
mov dl, BYTE PTR[edi]               ; move the next char into dl
cmp dl, 0                           ; check if token pointer is the null terminator
jnz LOWERCASE_TOKEN                 ; if not keep lowercasing the token
sub edi, ebx                        ; move the token pointer back to the first char
mov dl, BYTE PTR[edi]               ; ACCESSVIOLATIONEXCEPTION
xor ebx, ebx                        ; reset ebx
mov ecx, count                      ; set the counter for the loop

SEARCH :

mov eax, DWORD PTR[esi]             ; move the STUDENT ID to the result, eax
mov bl, BYTE PTR[esi + 4]           ; move the first char of the line being checked to bl
//add esi, 4                        ; move the list pointer to the first char
//mov bl, BYTE PTR[esi]             ; set bl to the first char of line being checked    
push ecx                            ; push the counter onto the stack
mov ecx, 1                          ; set ecx to be a line counter
//xor ecx, ecx                      ; zero out ecx

CHECK_LINE :
or bl, 0x20                         ; lowercase the char in the line being observed
cmp bl, dl                          ; check if the two char are equivalent
jne NEXT_LINE                       ; if not equal move to the next line
//add edi, 1                        ; move token pointer to the next char
//cmp BYTE PTR[edi], 0              ; check if next char in token pointer is the null terminator
cmp BYTE PTR[edi + ecx], 0          ; check if next byte in token pointer is the null terminator
jz DONE                             ; if so, finished searching
mov dl, BYTE PTR[edi + ecx]         ; move the next char in token to dl
//mov dl, BYTE PTR[edi]             ; move the next char in token to dl
mov bl, BYTE PTR[esi + ecx + 4]     ; move the next char in line being checked to bl
//add esi, 1                        ; move the list pointer to the next char
//mov bl, BYTE PTR [esi]            ; set bl to the next char
add ecx, 1                          ; increment the line counter
jmp CHECK_LINE                      ; continue checking line for equivalency

NEXT_LINE :
//sub esi, 4
//sub esi, ecx
//sub edi, ecx
add esi, 24                         ; move the list pointer to the next line
pop ecx                             ; pop loop counter back to ecx to maintain loop stability
LOOP SEARCH                         ; keep searching

DONE :

Q1:AccessViolationException

我指出了我在哪一行得到了 AccessViolationException,这是当我试图将指针移回后立即将令牌的第一个字符移回 dl 时。为什么会这样?

Q2:指针运算和字符串比较

当我遍历一串字符时,我尝试了不同的方法来移动指针,这就是我注释掉某些行的原因。我确定我的 LOWERCASE_TOKEN 从测试打印语句中以两种方式正确地小写了令牌,所以我只是不确定为什么当我真正开始搜索列表时它没有正确比较。我得到的清单是:

阿图罗·布莱恩·克里斯大卫·乔恩马克·肖恩·西蒙·托马斯·托尼

我已经在列表中测试了使用不同名称的搜索,即使令牌是列表中的名称之一并输出学生 ID 10,它也总是会遍历整个循环。

我没有正确搜索列表并比较每个元素吗??

【问题讨论】:

  • 如果您无法在 VM 中进行调试,请尝试在 VM 外部使用 gdb。用yasm 组装,用gcc -m32 链接(因为我看到你写了32 位代码,如果组装成x86-64 代码,它可能会截断地址和错误)。或者,如果不是地址截断问题,也许你会很幸运,有人会过来为你调试。
  • 我们看不到您如何定义tokenlist,因此我们无法判断您是否缺少间接级别(即您可能需要[token])。如果您要求其他人为您调试,您应该提供完整的工作代码。见MCVE。此外,虽然您的方式应该可行,但将edi 重置为token 的更安全方法是重新加载它而不是玩算术。
  • 尝试在你的虚拟机中使用 windbg 而不是 Visual Studio 调试器。

标签: assembly x86 access-violation string-comparison pointer-arithmetic


【解决方案1】:

编写了一个可行的不同实现:

xor eax, eax                ; zero out the result, eax
mov esi, list               ; move the list pointer to esi
mov edi, token              ; move the token pointer to edi
mov ecx, count              ; move the count to ecx
inc ecx                     ; increment the count for correct boundary test conditions

SEARCH:

xor ebx, ebx                ; a char counter
mov al, BYTE PTR[esi + 4]   ; move first char of a line to al
mov ah, BYTE PTR[edi]       ; move first char of token to ah
and al, 0xDF                ; uppercase the char
and ah, 0xDF                ; uppercase the char
cmp al, ah                  ; check if equal
jnz NEXT_LINE               ; if not move to next line

CHECK_LINE:

add ebx,1                   ; increment char counter
add esi,1                   ; move the list pointer to the next char
add edi,1                   ; move the token pointer to the next char
mov al, BYTE PTR[esi + 4]   ; move the list pointer char into al
mov ah, BYTE PTR[edi]       ; move the token pointer char into ah
and al, 0xDF                ; uppercase the char
and ah, 0xDF                ; uppercase the char
cmp al, ah                  ; check if equal
jnz NEXT_LINE               ; if not move to the next line
cmp al, 0x00                ; check for null terminator
jz NULL_CHECK               ; check for null terminator
jmp CHECK_LINE              ; keep searching line

NULL_CHECK:

cmp ah, 0x00                ; check if done
jz SUCCESSFUL_SEARCH        ; search completed

NEXT_LINE:

sub esi, ebx                ; move the list pointer back to the start of that line
cmp DWORD PTR[esi + 24], ecx; check if the end of the list has been reached
jz FAILED_SEARCH            ; if so token is not in list and search has failed
mov edi, token              ; reset the token pointer
add esi, 24                 ; move list pointer to the next line
jmp SEARCH                  ; continue searching the list

FAILED_SEARCH:

xor eax, eax                ; failed search, token not in list
jmp DONE                    ; end program

SUCCESSFUL_SEARCH:

sub esi, ebx                ; move list pointer to the beggining successful line
mov eax, DWORD PTR[esi]     ; place the students ID into the result

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-23
    • 2016-04-25
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 2021-11-03
    相关资源
    最近更新 更多