Menu
CoddyTech

不同宽度的 MOV

本课属于 Coddy Assembly 学习旅程的“基础知识”单元。第 20 课,共 45 课。

你已经使用过 al(8 位)和 rax(64 位)。不过还有其他大小的寄存器。不同的寄存器可以存储不同数量的数据。

x86-64 寄存器系列:

寄存器大小位数使用场景
rax8 字节64 位完整数值、地址、系统调用编号
eax4 字节32 位rax 的低半部分
ax2 字节16 位eax 的低半部分
al1 字节8 位ax 的低半部分(位 0-7)
ah1 字节8 位ax 的高半部分(位 8-15)

其他寄存器也遵循相同的模式:

64 位32 位16 位8 位(低位)
rbxebxbxbl
rcxecxcxcl
rdxedxdxdl
rsiesisisil
rdiedididil

为什么大小很重要:

移动数据时,源和目标的大小应当匹配。如果大小不匹配,CPU 可能会:

  • 只复制部分数据
  • 从未知内存中复制额外的字节
  • 导致错误

大小匹配示例:

mov rax, 1000        ; 64 位到 64 位(没问题)
mov eax, 1000        ; 32 位到 32 位(没问题)
mov ax, 1000         ; 16 位到 16 位(没问题)
mov al, 5            ; 8 位到 8 位(没问题)

大小不匹配时会发生什么:

mov rax, 0x123456789ABC   ; 64 位值
mov al, 0xFF              ; al 变为 0xFF,rax 的其他位保持不变

写入 8 位或 16 位寄存器(al、ah、ax)只会更改这些位,完整寄存器的其余部分保持不变。写入 32 位寄存器则不同:mov eax, 0xFF 会清除第 32 至 63 位,因此 rax 会变成 0xFF。这可能会导致意料之外的结果。

安全规则:

到目前为止,在这门课程中,内存中的所有数据都是 1 字节。这就是为什么你使用 al(而不是 rax)。

移动数据时,寄存器大小必须与内存大小匹配:

  • 1 字节内存 → 使用 al、bl、cl 等。
  • 8 字节内存 → 使用 rax、rbx、rcx 等。

你将在第 3 章学习不同的内存大小。

challenge icon

挑战

你已经创建了以下数据地址:

  • source:包含一个 1 字节的值(5)
  • destination:空闲空间(1 字节)

编写两行汇编代码来完成以下操作:

  1. 将 source 中的值加载到 al 中
  2. 将 al 中的值存入 destination

亲手试试

section .data
    msg db 'destination = '
    msg_len equ $ - msg

section .bss
    digit resb 1

section .text
    global _start

_start:
    ; 学生的代码先运行(从 source 加载,再存入 destination)
    
    %include "solution.asm"
    
    ; 从 destination 加载已存储的值
    mov al, [destination]
    
    ; 保存这个值
    mov r12, rax
    
    ; 打印 "destination = "
    mov rax, 1
    mov rdi, 1
    mov rsi, msg
    mov rdx, msg_len
    syscall
    
    ; 打印这个值
    mov rax, r12
    add rax, 48
    mov [digit], al
    mov rax, 1
    mov rdi, 1
    mov rsi, digit
    mov rdx, 1
    syscall
    
    ; 退出
    mov rax, 60
    mov rdi, 0
    syscall
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

基础知识中的所有课

自己练习: Assembly 在线编辑器