ASM如何知道算术运算是有符号的还是无符号的? [英] How does ASM knows an arithmetic operation is signed or unsigned?

查看:124
本文介绍了ASM如何知道算术运算是有符号的还是无符号的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am assembling using MASM 14.0, and i am confused with the output of the below code.

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

这两种算术运算都是在无符号整数255和127上完成的.

Both arithmetic operations are done on unsigned integers 255 and 127.

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

However, the CPU is treating the first operation 255, as an unsigned integers and setting the carry flag, which would happen when you add 1 to an unsigned 255.

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

The complete status flags are CF=1 SF=0 ZF=1 OF=0 AF=1 PF=1 with eax as 0

但是,第二个操作将127设置为溢出标志,因此认为127是有符号整数,如果您将+127加1,则会发生这种情况.

But, the second operation considers the 127 to be a signed integer as it is setting the overflow flag, which would happen if you add 1 to a +127.

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

The complete status flags are to CF=0 SF=1 ZF=0 OF=1 AF=1 PF=0 with eax as 0.

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

The question is how does the CPU decides that the first operation was done on an unsigned 255, while the other one was on a signed integer?

推荐答案

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

For addition (and subtraction) using twos complement there is no notion of signed or unsigned as far as the logic is concerned. Multiply and divide, yes, due to the sign extension required.

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

Take all combinations of 3 bit numbers from 000 to 111 and add them to all the combinations of 3 bit numbers, something manageable. Maybe write a program if you want or do it by hand. Or just do the corner cases. For each examine each operand as signed or unsigned using twos complement. You will note that the same addition works. 1 + 110 = 111. Now is that 1 + (-2) = -1 or was that 1 + 6 = 7. Both worked.

进位标志是UNSIGNED溢出,V标志是SIGNED溢出,这就是我们计算两者的原因,因此,知道那些有符号或无符号数字的用户可以选择正确的条件.这就是为什么您在大于或等于的情况下对有符号的跳转进行了对比,而在大于或等于的情况下对无符号的进行了跳转的原因.

The carry flag IS the UNSIGNED overflow, the V flag is the SIGNED overflow, that is why we compute both so the user, who knows whether or not those are signed or unsigned numbers can choose the right conditional. And that is why you have signed jump if greater than or equal vs an unsigned jump if greater than or equal.

使之奏效的是二进制补全之美.

It is the beauty of twos complement that makes it all work.

乘法(除法)是不同的,因为必须对扩展符号进行签名.以二进制形式相乘具有一个美丽的功能,那就是如果您考虑一下

Multiply (and divide) is different, because you have to sign extend. Multiply in binary has a beautiful feature, in that if you think about it

   abcd
*  0011
=======
   abcd
  abcd
 0000
0000
=======

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

A bit is either 1 or 0, so you are multiplying the top number by either one or zero, you either add it shifted or you dont. But also notice that very very quickly you are going to overflow. We know from grade school that n^x * n^y = n^(x+y). If your registers are Z bits wide the most significant bit positions of the operands cannot be larger than Z when added otherwise it overflows. Four bits 0010*0010 should work but 0010*1000 will overflow. The right way is the result is twice as wide as the operands.

那我想乘1111 * 0010怎么办?

So what if I want to multiply 1111 * 0010?

基本上是

    0000
   1111
  0000
+0000
========
 0011110

是15(0b1111)还是-1(0b1111)? -1 * 2 = -2这不是我们上面得到的,我们执行了无符号乘法来执行有符号乘法,我们必须对扩展名进行符号化并将位抛向左

Wait was that a 15 (0b1111) or a -1 (0b1111)? -1 * 2 = -2 which is not what we got above, we did an unsigned multiply to do a signed multiply we have to sign extend and toss bits off the left

 11..1111
*00..0010
=========    
00000000
1111111
000000
00000
=========
11111110

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

and that gives the right answer for a signed multiply of two four bit registers 1111 and 0010.

加法有效,因为您只关心一列.每列都有一个进位,两个操作数一个结果和一个进位.然后,您可以根据需要将其级联起来.一位只有0和1.零只是零而不是正负零,1可以是+1或-1.我发现处理多于一列的组合更容易,但是可以做到.另外,进位值是0,因此我不需要将其表示为操作数a,操作数b,执行和结果

Addition works because you only care about one column. Each column has a carry in, two operands a result and a carry out. And then you can cascade that as wide as you want. With a single bit you have 0 and 1. The zero is just zero not plus or minus zero, the 1 can either be a +1 or a -1. I find it easier to work through the combinations with more than one column, but it could be done. For addition the carry in is a 0 so I dont need to represent it operand a, operand b, carry out, and result

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

从技术上讲,所有已签名的都是后一种情况下的有符号溢出,这就是您要处理的任意位数的特殊情况,取一个三位寄存器100 + 100 = 000 +进行1运算是4 + 4 = 0无符号溢出,或者是-4 + -4 = 0有符号溢出?这就是为什么更容易看到何时使用一些位并进行组合处理来将问题情况从1转换为全零的原因.

Technically all the signed ones were a signed overflow in that last case, and that is the special case you deal with for any number of bits, take a three bit register 100 + 100 = 000 + carry out of 1 is that a 4 + 4 = 0 unsigned overflow or is that a -4 + -4 = 0 with a signed overflow? Which is why it is easier to see when you use a few bits and go through the combinations tossing the problem case of 1 and then all zeros.

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

A signed overflow is when the carry in of the most significant column does not match the carry out. an unsigned overflow is when the carry out of the msbit is a one.

逻辑上的减法是加法完成的,我们从小学时就知道a-b = a +(-b),并且从编程课上知道,使用二进制取负可以求反,然后加一.很好,这很好,我们可以将第二个操作数求反,并将lsbit的进位求反,使之成为1,或者求反并加1.这就是它的工作原理.有时将进位额从alu倒过来表示借位.您必须查看标志组合才能弄清楚这一点,有些处理器会将进位反转,有些则不要.有时可以通过减法从借位中分辨出您的ISA是否有该指令.

Subtraction in logic is done with addition, we know from grade school that a - b = a + (-b) and we know from programming classes that to take the negative using twos complement you invert and add one. Well that works great we can just invert the second operand and invert the carry in of the lsbit making it a one or invert and add one. And that is how that works. The carry out is sometimes inverted coming out of the alu to indicate a borrow. You have to look at the flag combinations to figure this out, some processors invert the carry out some dont. Can sometimes tell from the subtract with borrow if your ISA has that instruction.

我知道TL:DR ...比您要求的要多.

I know TL:DR...covered more than you asked.

这篇关于ASM如何知道算术运算是有符号的还是无符号的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆