在x86-64 Tour of Intel Manuals中,我读到了
也许最令人惊讶的事实是,诸如
MOV EAX, EBX自动将指令的高32位归零的指令RAX.
同一来源引用的英特尔文档(3.4.1.1 64位手动基本架构中的通用寄存器)告诉我们:
- 64位操作数在目标通用寄存器中生成64位结果.
- 32位操作数生成32位结果,在目标通用寄存器中零扩展为64位结果.
- 8位和16位操作数生成8位或16位结果.目标通用寄存器的高56位或48位(分别)不会被操作修改.如果8位或16位操作的结果用于64位地址计算,则将寄存器显式符号扩展为完整的64位.
在x86-32和x86-64汇编中,16位指令如
mov ax, bx
不要表现出这种"奇怪"的行为,即eax的上层词被归零.
因此:引入这种行为的原因是什么?乍一看似乎不合逻辑(但原因可能是我习惯了x86-32汇编的怪癖).
正如广泛宣传的那样,现代x86_64处理器具有64位寄存器,可以以向后兼容的方式用作32位寄存器,16位寄存器甚至8位寄存器,例如:
0x1122334455667788
  ================ rax (64 bits)
          ======== eax (32 bits)
              ====  ax (16 bits)
              ==    ah (8 bits)
                ==  al (8 bits)
这样的方案可以从字面上理解,即,总是可以使用指定的名称仅访问寄存器的一部分用于读取或写入目的,并且这将是高度逻辑的.实际上,对于高达32位的所有内容都是如此:
mov  eax, 0x11112222 ; eax = 0x11112222
mov  ax, 0x3333      ; eax = 0x11113333 (works, only low 16 bits changed)
mov  al, 0x44        ; eax = 0x11113344 (works, only low 8 bits changed)
mov  ah, 0x55        ; eax = 0x11115544 (works, only high 8 bits changed)
xor  ah, ah          ; eax = 0x11110044 (works, only high 8 …组装此代码时nasm:
BITS 64
mov eax, 0x1
mov rax, 0x1
我得到这个输出:
b8 01 00 00 00 b8 01 00 00 00
这是mov eax, 0x1重复两次的操作码.
这是否意味着mov rax, 0x1可以随时被替换mov eax, 0x1,或只是在这种情况下?
如果这是正确的,那么使用它不是更好:
xor rax, rax
inc rax
因为组装时变为6个字节,而mov eax, 0x1只有5个字节?
我决定学习汇编编程语言.我正在使用这个.在底部练习它在一些指令中找到错误,其中之一是
mov cx, ch 
我在SO上发现了一些类似的问题,解释了如何实现它,但现在我想知道为什么禁止这个操作?
假设我在CH中有10d = 00001010b并且想要将其置于CL并同时擦除CH.mov cx, ch似乎这样做是因为它将10d显示为16bit 00000000 00001010并将其分别放入CH和CL(整个CX)
有什么问题,为什么给定的教程要求在这个表达式中找到错误?
好吧,所以我正在处理以下代码片段:
push   %ebp
mov    %esp,%ebp   
push   %ebx
mov    0x8(%ebp),%eax 
movzwl %ax,%edx
所以这在处理正值时表现得像预期的那样.复制到%edx中的值是%eax(或%ax)的尾随16位.
但是,如果你输入一个负数,一切都开始变得怪异,它似乎没有像预期的那样表现.
例如,如果%eax的值为-67043552,则复制到%edx的值为65312.
我很擅长集会,对不起,如果这对我来说是一个明显的误解.任何帮助将不胜感激.
我正在设计 MIPS 处理器作为我的个人项目,现在我遇到了一个非常困惑的问题。我只是无法总结何时在 MIPS 中使用有符号扩展以及何时使用零扩展。
我搜索了很多资源,主要是说:
1) ADDI, ADDIU 都是使用signed-extend。
2) ANDI、ORI、XORI 都使用零扩展。
但是,在这两条指令中,我开始感到困惑:
SLTIU/SLTI
在 Imagination 的“程序员的 MIPS 架构第 II-A 卷:MIPS 指令集手册”第 368 页中说:

它清楚地提到16位立即数是signed-extend。但我不明白以下语句:
[0, 32767] 或最大 [max_unsigned-32767, max_unsigned] 无符号范围的结尾。
其他一些人说 16 位立即数是零扩展,如下所示:

那么,有人可以解释一下 MIPS 中的有符号指令和无符号指令之间究竟有什么区别吗?
assembly mips system-verilog zero-extension immediate-operand
我正在学习MOV汇编中的数据移动()。
我尝试编译一些代码以查看 x86_64 Ubuntu 18.04 机器中的程序集:
typedef unsigned char src_t;
typedef xxx dst_t;
dst_t cast(src_t *sp, dst_t *dp) {
    *dp = (dst_t)*sp;
    return *dp;
}
哪里。src_t unsigned char至于,dst_t我试过了char,,short和int。long结果如下所示:
// typedef unsigned char src_t;
// typedef char dst_t;
//  movzbl  (%rdi), %eax
//  movb    %al, (%rsi)
// typedef unsigned char src_t;
// typedef short dst_t;
//  movzbl  (%rdi), %eax
//  movw    %ax, (%rsi)
// typedef unsigned …我正在查看以下反汇编的 AArch64 指令:
65 6E 20 2B    adds w5, w19, w0, uxtx #3
根据 ARM 手册,在将其添加到 中的值之前,uxtx先将其零扩展w0为无符号 64 位值w19。Butw19是 的 32 位“切片” x19,结果存储在 的 32 位切片中x5。也就是说,操作值的大小不同。
问题不限于adds;其他 AArch64 指令类似add或sub表现出相同的编码。这个问题也适用于 64 位sxtx签名扩展,由于符号扩展问题,很可能它的行为与 32 位sxtw.
当与 32 位寄存器切片一起使用时,uxtx和 的sxtx作用是否与和uxtw完全相同?sxtx如果是这样,那么 ARM 通过支持这些表面上相同的操作的编码[us]xtw和[us]xtx扩展编码来提供什么价值?如果不是,用户程序是否可以看到差异?
对于x86和x64编译器,生成类似的零/符号扩展MOVSX和MOVZX.扩展本身并不是免费的,但允许处理器执行无序魔术加速.
但是在RISC-V上:
因此,无符号和带符号的32位整数之间的转换是无操作,从有符号的32位整数到带符号的64位整数的转换也是如此.
添加和移位需要一些新指令(ADD [I] W/SUBW/SxxW)以确保32位值的合理性能.
(C)RISC-V Spec
但与此同时,新的现代RISC-V 64位处理器包含32位有符号整数的指令.为什么?提高性能?那么8位和16位呢?我已经什么都不懂了.
假设 $t2= 0x55555550,然后执行以下指令:
andi $t2, $t2, -1
$t2 变成 0x0005550
MIPS 仿真器1证实了这一点
然而,这不是我所期望的。我认为答案应该是 0x55555550 & 0xFFFFFFFF = 0x55555550。我认为常量 -1 在和逻辑之前被符号扩展为 0xFFFFFFFF。但似乎答案是 0x55555550 & 0x0000FFFF
为什么 -1 被符号扩展为 0x0000FFFF 而不是 0xFFFFFFFF
脚注 1:编者注:启用“扩展伪指令”的 MARS 确实将其扩展为多条指令以0xffffffff在 tmp 寄存器中生成,因此保持$t2不变。否则 MARS 和 SPIM 都会以不可编码的错误拒绝它。其他汇编程序可能有所不同。
assembly mips sign-extension zero-extension immediate-operand
如何解决将8位值移至BX寄存器(16位)的问题?
mov al, 10h
mov bx, al
为此,我得到:
operands do not match: 16 bit and 8 bit register