在cmp指令x86中携带标志

时间:2014-06-22 19:41:22

标签: assembly x86

我是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技巧。

2 个答案:

答案 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指令将其输入到寄存器中。