Conditional jump not taken
我是用汇编(x86,linux)开头,只是为了好玩。这是我的第一个小程序,它只检查我是否通过命令行传递了一个参数,如果没有,它会打印一条消息,然后退出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| section .text
global _start
_start:
pop ebx ;argc
dec ebx
test ebx,1
jne print_string
exit:
mov ebx,0
mov eax,0
int 0x80
print_string:
mov edx,len
mov ecx,msg
mov ebx,1
mov eax,4
int 0x80
call exit
section .data
msg db "Ok, no arg was passed",0xa
len equ $ - msg |
我有两个问题的问题:
jne 不被采用。我用 gdb 检查了 ebx 在 dec 之后等于 0x00,但是 EFLAGS 不会被 test 指令更改。
退出系统调用不退出!因此,我没有退出,而是在无限循环中打印了我的消息,因为 print_string 正在调用 exit 并且退出后 print_string 一遍又一遍地进行。
这里发生了什么?还欢迎关于代码的任何其他建议。谢谢。
- test 不会按照你的想法去做。你想要一个 cmp。此外,您需要 je 而不是 jne。 exit 的系统调用号是 1 而不是 0。
-
好的,这行得通。似乎我需要阅读更好的资料。如果您有兴趣发布任何关于跳转和 cmp 的良好参考的答案,我将很高兴将其标记为正确...
-
通常像"x86 指令测试"这样的谷歌搜索会导致指令参考指南的 HTML 版本之一,如 http://x86.renejeschke.de/ 和类似的。有时它们包含微小的不准确之处,但通常它们是检查(与调试器一起)如果某些东西没有按预期工作的第一件事。只有当调试器证明那些缩短的版本是错误的时,才需要深入研究英特尔官方文档(英特尔网站上免费提供的 pdf),或者交叉检查几个快速参考。对于 ASM 中的编程,必须同时使用两者:调试器文档
test 指令在不改变寄存器操作数的情况下按位执行and。
test ebx,1 执行:flags = (ebx and 1)。或 ZF = IsEven(ebx)。
如果要测试 ebx = 1 是否需要使用 cmp。
cmp 执行减法而不更改寄存器操作数。
cmp ebx,1 执行 flags = ebx - 1 或 ZF = (ebx = 1).
系统调用退出
您为 exit() 设置了错误的参数。
正确的代码是:
1 2 3 4
| exit:
mov ebx,0
mov eax,1 <<--
int 0x80 |