算术中的汇编位内存限制

时间:2016-09-19 18:32:48

标签: assembly x86 nasm masm irvine32

我想添加以下数字:40,90,50和155,我总共得到355。

我想试验并测试寄存器AL是否有一个位限制为(2 ^ 8) - 1,当我编译代码并执行代码时,我得到1376331855的小数。这是怎么发生的?

另外,我认为355大于255,因此应该显示溢出异常。

我理解如果我使用MOVZX,我将能够将计算结果带入AX的更高寄存器。

另外,我对AL和AH之间的区别很困惑。 AL和AH的内存分配是否有所不同?

TITLE Adding              
INCLUDE Irvine32.inc

.code
main PROC

    mov al,0h             ; 
    add al,28h            ; 40

    add al,5Ah            ; 90 
    add al,32h            ;50
    add al,9Bh            ;155
                            ; total is 355
    call DumpRegs
    call writedec

exit
main ENDP
END main

2 个答案:

答案 0 :(得分:3)

  

另外,我对AL和AH之间的区别很困惑。 AL和AH的内存分配是否有所不同?

不,没有记忆。它们都是EAX中的字节寄存器。

  • AX是EAX的低16位
  • AH和AL是AX
  • 的高半部分和低半部分

另见this ascii-art diagram。或者在C:

union eax {
    uint32_t EAX;                // regs aren't really signed or unsigned, but they have well-defined wraparound semantics like C unsigned (and unlike C signed).
    uint16_t AX;
    struct { uint8_t AL, AH; };  // anonymous struct, in little-endian order (AL is the low byte).
};

写入任何成员都会反映在其他成员的值中,但不会将其余部分归零。 (footnote1)

您的打印功能会打印所有EAX,但在打印之前,您永远不会将EAX的高字节归零。 在进入main时,您需要假设EAX的所有字节都是随机垃圾

main PROC

    xor    eax, eax       ; zero eax
    ; mov al,0h      ; instead of just zeroing al and leaving garbage in the upper 24 bits
    add    al,28h         ; then play around with the low byte if you want
    ...
    add    al,9Bh         ; AL wraps around, but no carry happens into the rest of EAX.
    ;  If you want that, use a wider register:
    ; add   eax, 9Bh

    call writedec         ; prints eax as a signed integer
  

我认为355大于255,因此应该显示溢出异常。

整数溢出设置标志,您可以稍后测试。 请参阅Understanding Carry vs. Overflow conditions/flags

它不会触发故障/异常。 (除了分裂)

(1):严格的ISO C90和ISO C ++实际上不允许读取不是最后写入的联合成员(未定义的行为)。 ISO C99, (and GNU C++ as an extension) do guarantee type-punning with unions works as expected

答案 1 :(得分:2)

据我了解,DumpRegs为您提供EAX的输出。当我将你的答案转换为HEX时,我得到5209284F,4F在AL中。 4F HEX为79十进制,为335 - 256.AL寄存器仅保存8位,因此256是它可以容纳的最大无符号整数。

在开始之前清除EAX,结果可能更有意义。