我是x86的新手,我试图将更大的整数(位置4(%esp)和8(%esp))放入寄存器%eax。根据我的理解,我的cmp命令会将进位标志设置为1或0,然后adc将该标志传送到eax寄存器。然后我可以通过从esp中偏移4 + flag * 4来获得我想要的值。它似乎适用于所有情况,除了负值,我有点困惑?
movl 4(%esp), %ecx
cmp 8(%esp), %ecx
movl $0, %eax
adc $0, %eax
movl 4(%esp, %esp, 4), %eax
P.S。我不允许跳跃/分支或快速的arithemtic技巧。
答案 0 :(得分:3)
与大多数两个补码表示CPU一样,x86实际上并不知道您的号码是否已签名。你只需按照自己的想法对待它们。
当你进行比较时,你真的在做一个"减去"并把答案扔掉了。进位位设置为"借用"从无符号中减去两个数字。如果您正在检查进位,在进行比较后,您实际上断言数字是无符号的。因此,您对签名号码的答案是错误的。
如果您想比较两个签名的号码,您需要查看差异的符号。如果值足够大,那么符号就会出现问题,因此差异会导致溢出,但是我们可以通过使用等于"跳转符号小于"来解决这个问题。 (大多数x86汇编程序中的JLT),考虑到这一点。
所以按照你的风格编写代码的简单方法是:
movl 4(%esp), %ecx
cmp 8(%esp), %ecx
movl $0, %eax
jlt L1
add $1, %eax
L1: movl 4(%esp, %esp, 4), %eax
但是你说你不能使用jmp指令。幸运的是,有一条指令基本上可以实现" jlt ..添加$ 1"对确实叫" setge", 但它只在AL中给出答案。因此,在将条件插入底部字节之前,我们需要movl $ 0将所有eax归零。 (对于指令集中的每个jcc,都有一个setcc)。所以这会奏效:
movl 4(%esp), %ecx
cmp 8(%esp), %ecx
movl $0, %eax
setge %al ; use opposite condition than above jle
L1: movl 4(%esp, %esp, 4), %eax
有一个更方便的指令:mov conditional(cmov), 如果某些条件(任何可能的jmp条件)为真,它会将值移动到寄存器。
movl 4($esp), %eax
movl 8($esp), %ecx
cmp %ecx, %eax
cmovge %ecx, %eax
OP的家庭作业:去查看mov条件指令,了解其工作原理。
(我不是AT& T汇编语言语法专家;可能会出现上述小错误。)
答案 1 :(得分:2)
进位标志包含两个值的无符号比较结果 - x86用语中的AE
(大于或等于)比较。如果需要签名比较,则需要使用GE
(大于或等于)比较,该比较测试符号和溢出标志是否相等(进位标志无关紧要)。您可以使用setge
指令将其输入到寄存器中。