我正在努力学习装配。我使用NASM而不是AT& T语法。
这是我的第一个程序,它比较两个命令行参数和输出哪个是最小的(如果它们相等则支持第一个)。
我想我做错了。我注意到堆栈随着compare的每次“调用”而增长,所以我可以通过尾递归优化来改善它。但是,我不知道如何正确地做到这一点。我应该用其他东西替换所有出现的'call',比如jmp吗? 我读到跳跃的方式也取决于你如何链接linux内核和/或libc关于'函数'对象(我没有链接libc,因此没有主'功能'),这让我困惑所以我以为我会来这里寻求简单的简短建议。
另外,我遇到的另一个问题是“jl”紧跟“jg”是多么愚蠢,如果“jl”跳转实际上改变了标志内容所以“jg”也会跳跃,这可能会导致不必要的行为。是否存在双向“原子”跳跃?
section .data
usage: db 'Please provide two strings',10
usageLen: equ $-usage
bigger: db 'It is bigger!',10
biggerLen: equ $-bigger
smaller: db 'It is smaller!',10
smallerLen: equ $-smaller
section .text
global _start
_start:
pop ebx ; argc
cmp ebx, 3
jne usage_exit
pop eax ; argv[0]
pop eax
pop ebx
call compare ;
usage_exit:
mov eax, 4 ; sys_write
mov ebx, 1 ; int fd = stdout
mov ecx, usage
mov edx, usageLen
int 80h ; call kernel
mov eax, 1 ; sys_exit
mov ebx, 0 ; int status = 0
int 80h ; call kernel
report:
mov ecx, eax
mov edx, ebx
mov eax, 4 ; sys_write
mov ebx, 1 ; int fd = stdout
int 80h ; call kernel
mov eax, 1 ; sys_exit
mov ebx, 0 ; int status = 0
int 80h ; call kernel (exit)
compare:
push eax
push ebx
mov eax, [eax]
mov ebx, [ebx]
test ax, ax
jz is_smaller
test bx, bx
jz is_bigger
cmp ax, bx
jl is_smaller
jg is_bigger
; if the same, try next positions
pop ebx
pop eax
inc eax
inc ebx
call compare
is_smaller:
mov eax, smaller
mov ebx, smallerLen
call report
is_bigger:
mov eax, bigger
mov ebx, biggerLen
call report
答案 0 :(得分:5)
是的,您应该将call
替换为jmp
s。通常,当您希望在调用返回时在下一行继续执行时,应使用call
。在您的代码中,执行永远不会返回,因为compare
只是一个循环,所以jmp
是进入下一次迭代的正确方法。对于您拥有的call report
的两个实例也是如此。
至于你的第二个问题,jl
没有改变标志,所以在它之后调用jg
没有问题。