我曾经用TASM(在winXP上)编译我的asm代码,但是现在我有一些麻烦,所以现在我使用NASM(在linux上)。 这个片段显示了我想要做的事情:
(gdb) list 35 30 xor ecx,ecx # ecx is a counter 31 mov bl,' ' # this is what I'm looking for 32 count_spaces: 33 mov al,[esi] # grab a char 34 jz spaces_counted # is this the end? 35 inc esi # next char 36 cmp al,bl # found one? 37 jne count_spaces # nope,loop 38 inc ecx # yep,inc counter 39 jmp count_spaces # and loop
这看起来对我来说是正确的, 但是 :
Breakpoint 1,main () at project1.asm:30 30 xor ecx,ecx (gdb) display (char) $al 1: (char) $al = 0 ' 00' (gdb) display (char) $bl 2: (char) $bl = 0 ' 00' (gdb) next 31 mov bl,' ' 2: (char) $bl = 0 ' 00' 1: (char) $al = 0 ' 00' (gdb) count_spaces () at project1.asm:33 33 mov al,[esi] 2: (char) $bl = 0 ' 00' 1: (char) $al = 0 ' 00' (gdb)
我不明白为什么al和bl没有改变。
我敢肯定我的代码是正确的,但..我想我错过了一些NASM的select? 顺便说一句,我编译
nasm -f elf -l project1.lst -o project1.o -i../include/ -g project1.asm
编译完成后,我拆开输出,得到:
Linux在堆栈上使用string编写sys调用
__RTC_CheckEsp如何实现?
assembly和string中的分割错误
retq和ret有什么区别?
在C中写入Bootloader
80483ec: 31 c9 xor %ecx,%ecx 80483ee: bb 20 00 00 00 mov $0x20,%ebx 080483f3 <count_spaces>: 80483f3: 8b 06 mov (%esi),%eax 80483f5: 3d 00 00 00 00 cmp $0x0,%eax 80483fa: 74 0b je 8048407 <spaces_counted> 80483fc: 46 inc %esi 80483fd: 39 d8 cmp %ebx,%eax 80483ff: 75 f2 jne 80483f3 <count_spaces> 8048401: 41 inc %ecx 8048402: e9 ec ff ff ff jmp 80483f3 <count_spaces>
如何让asm跳转到c中的variables地址?
Linux如何保护内存?
在Win32上使用FASM进行SDL Ret失败
为什么这个简单的汇编程序使用AT&T语法,而不是英特尔语法?
将符号从.globl改为.weak有什么后果?
请注意,GDB不知道8位或16位别名寄存器。 它总是会为al,bl,ax,bx等打印0。你应该使用eax,ebx等:
(gdb) info registers bl Invalid register `bl' (gdb) info registers bx Invalid register `bx' (gdb) info registers ebx ebx 0xf7730ff4 -143454220 (gdb) p $bl $1 = void (gdb) p $bx $2 = void (gdb) p $ebx $3 = -143454220 (gdb) p/x $bl $4 = Value can't be converted to integer. (gdb) p/x $bx $5 = Value can't be converted to integer. (gdb) p/x $ebx $6 = 0xf7730ff4 (gdb) p (char) $bl $7 = 0 ' ' (gdb) p (char) $bx $8 = 0 ' ' (gdb) p (char) $ebx $9 = -12 'ô'
杰斯特有正确的答案 ,值得投票。
但是,我想添加一些太长的评论:如果你愿意的话,你可以教gdb显示子寄存器,使用在任何display之前运行的hook-stop钩子 ,通过添加以下内容您的.gdbinit文件:
define hook-stop set $bl=($ebx & 0xff) set $bh=(($ebx & 0xff00) >> 8) set $bx=($ebx & 0xffff) end
(以其他寄存器的明显方式扩展)。 display $bl等,然后将按预期工作。
我不确定这是否是您已经注意到的问题,但我在您的代码中看到一个相当明显的问题。 在x86上, mov不会影响标志。 你的代码:
33 mov al,[esi] # grab a char 34 jz spaces_counted # is this the end?
似乎假设当你从[esi]加载al时, z标志将被更新以反映al的内容。 事实并非如此。 要测试你刚加载的值是否为零,你需要添加一个明确的测试:
mov al,[esi] test al,al jz spaces_counted
寄存器中的值之前应该已经更改,但标志不应该更新以反映值。
至于nasm是否产生了正确的说明,我会反汇编代码,看看有什么真正的。 现在很难猜测问题出在nasm还是gdb上。 当然,反汇编程序也不能保证没有错误,但是如果看到代码问题很简单,我会有些惊讶。
标志不被mov修改,所以第34行的jz是没有意义的。 如果你按照最初的xor的代码,这是修改标志的唯一指令,所以当代码到达第34行的jz时,它只是跳转(因为xor它留给零)。 这并不能解释al或bl的非变化值,但是可能会考虑到因为xor而始终执行jz的一些优化。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。