ASM如何知道算术运算是有符号还是无符号?

Saa*_*aad 5 x86 assembly masm irvine32

我正在使用MASM 14.0进行组装,我对以下代码的输出感到困惑.

TITLE Exercise 4 from chapter 4

; Author : Saad Ahmed

INCLUDE Irvine32.inc

.code
main PROC

mov eax, 0
mov al, 255
add al, 1
call DumpRegs       ; Display registers

mov al, 127
add al, 1
call DumpRegs       ; Display registers

exit
main ENDP
END main
Run Code Online (Sandbox Code Playgroud)

两个算术运算都在无符号整数255和127上完成.

但是,CPU将第一个操作255视为无符号整数并设置进位标志,当您将1添加到无符号255时会发生这种情况.

完整的状态标志是CF = 1 SF = 0 ZF = 1 OF = 0 AF = 1 PF = 1,eax为0

但是,第二个操作将127视为有符号整数,因为它设置了溢出标志,如果你将1加到+127就会发生这种情况.

完整的状态标志为CF = 0 SF = 1 ZF = 0 OF = 1 AF = 1 PF = 0,eax为0.

问题是CPU如何确定第一个操作是在无符号255上完成的,而另一个是在有符号整数上?

old*_*mer 9

对于使用二进制补码的加法(和减法),就逻辑而言,没有有符号或无符号的概念.乘以和除,是的,由于需要符号扩展.

将3位数字的所有组合从000到111并将它们添加到3位数的所有组合中,这是可管理的.如果你想要或者手工做,也许可以写一个程序.或者只是做角落案件.对于每个操作数,使用二进制补码检查每个操作数是有符号还是无符号.您会注意到相同的添加工作.1 + 110 = 111.现在是1 +( - 2)= -1或是1 + 6 = 7.两者都有效.

进位标志是UNSIGNED溢出,V标志是SIGNED溢出,这就是我们计算两者的原因所以用户知道那些有符号或无符号的数字是否可以选择正确的条件.这就是为什么如果大于或等于大于或等于无符号跳跃,则签名跳转.

这是两个补充的美丽,使一切工作.

乘(和除)是不同的,因为你必须签署扩展.乘二进制有一个漂亮的功能,如果你考虑它

   abcd
*  0011
=======
   abcd
  abcd
 0000
0000
=======
Run Code Online (Sandbox Code Playgroud)

一个位是1或0,所以你将顶部数字乘以1或0,你可以添加它移位或你不.但是也要注意到你很快就会溢出来.我们从小学就知道n ^ x*n ^ y = n ^(x + y).如果寄存器为Z位宽,则操作数的最高有效位位置在添加时不能大于Z,否则溢出.四位0010*0010应该工作但是0010*1000将溢出.正确的方法是结果是操作数的两倍.

那么如果我想乘以1111*0010怎么办?

基本上就是这样

    0000
   1111
  0000
+0000
========
 0011110
Run Code Online (Sandbox Code Playgroud)

等一下是15(0b1111)还是-1(0b1111)?-1*2 = -2这不是我们上面得到的,我们做了一个无符号乘法来做一个有符号的乘法我们必须签署扩展并抛出左边的位

 11..1111
*00..0010
=========    
00000000
1111111
000000
00000
=========
11111110
Run Code Online (Sandbox Code Playgroud)

并且这给出了两个四位寄存器1111和0010的有符号乘法的正确答案.

添加有效,因为您只关心一列.每列都有一个进位,两个操作数,一个结果和一个执行.然后你可以根据需要将它级联起来.使用单个位,您有0和1.零只是零而不是正负零,1可以是+1或-1.我发现使用多个列可以更轻松地完成组合,但是可以完成.为了加法,进位是0,所以我不需要表示它的操作数a,操作数b,执行和结果

00 00  0 + 0 = 0
01 01  0 + 1 = 1;  0 + (-1) = -1
10 01  1 + 0 = 1;  (-1) + 0 = -1
11 10  1 + 1 = 0 unsigned overflow.  -1 + 1 = 0, 1 + -1 = 0, -1 + -1 = 0 signed overflow
Run Code Online (Sandbox Code Playgroud)

从技术上讲,在最后一种情况下,所有已签名的溢出都是有符号溢出,这是您处理任意位数的特殊情况,取三位寄存器100 + 100 = 000 +执行1是4 + 4 = 0无符号溢出或带有符号溢出的-4 + -4 = 0?这就是为什么当你使用几个比特并且通过组合抛出问题情况1然后全部为零时更容易看到的原因.

有符号溢出是指最高有效列的进位与执行不匹配.无符号溢出是指msbit的执行是1.

逻辑中的减法是通过加法来完成的,我们从小学就知道a - b = a +( - b)并且我们从编程类中知道要使用二进制补码来反转并添加一个.那么工作得很好我们可以反转第二个操作数并反转lsbit的进位使其成为一个或反转并添加一个.这就是它的工作原理.执行有时会从alu中反转出来以表示借入.你必须看看标志组合来解决这个问题,有些处理器会将执行结果反转一些.如果您的ISA有该指令,有时可以通过借用减去判断.

我知道TL:DR ...覆盖的比你提出的要多.


Blo*_*ard 5

两个补码的好处是CPU不需要知道.

它只是在无符号字节上添加.

进位标志被设置,因为255 + 1不适合8位(显然).

设置溢出标志是因为两个操作数的MSB都是0,并且输出的MSB是1 - 表示如果你认为这是带符号的算术,你就会溢出.如果你认为它是无符号算术,那么你应该忽略该标志.请参阅此维基百科文章.

  • 加法和减法为真......对于乘法和除法,有单独的有符号和无符号指令. (3认同)