【发布时间】: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 代码,它可能会截断地址和错误)。或者,如果不是地址截断问题,也许你会很幸运,有人会过来为你调试。 -
我们看不到您如何定义
token和list,因此我们无法判断您是否缺少间接级别(即您可能需要[token])。如果您要求其他人为您调试,您应该提供完整的工作代码。见MCVE。此外,虽然您的方式应该可行,但将edi重置为token的更安全方法是重新加载它而不是玩算术。 -
尝试在你的虚拟机中使用 windbg 而不是 Visual Studio 调试器。
标签: assembly x86 access-violation string-comparison pointer-arithmetic