Menu
CoddyTech

缓冲区地址(rsi)

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

在 write 系统调用中,告诉操作系统将输出发送到哪里(rdi 中的文件描述符)后,你还需要告诉它要打印什么。为此,你需要传入字符串在内存中的地址。

缓冲区地址的寄存器是 rsi。

什么是缓冲区?

缓冲区就是一块用于存放数据的内存。在这里,缓冲区是我们想要打印的字符串。

为什么传递地址,而不是值本身?

write 系统调用需要知道字符串在内存中的起始位置。它会从该地址开始读取字节,直到达到你在 rdx 中指定的长度。你不会把实际字符传递给系统调用,而是传递它们的位置。

示例:

section .data
    msg db 'Hello', 0x0a

section .text
    mov rsi, msg        ; rsi 保存着 msg 的地址

msg 到底是什么:

msg 是一个标签。汇编器会将它替换为一个数字:字符串 'Hello' 存储位置的内存地址。当你写下 mov rsi, msg 时,就是把这个地址数字放入 rsi。

如果忘记地址会怎样?

如果你没有设置 rsi,寄存器中就会保留之前的任意垃圾值。操作系统会尝试从该地址读取字符串。如果该地址无效,write 系统调用就不会打印任何内容,会将错误代码放入 rax,然后程序继续执行下一条指令。如果遗留的值恰好是可读内存的地址,系统调用就会打印存储在那里的字节。

包含写入系统调用的完整示例:

section .data
    msg db 'Hello', 0x0a
    len equ $ - msg

section .text
    mov rax, 1          ; write 系统调用
    mov rdi, 1          ; stdout
    mov rsi, msg        ; 字符串的地址
    mov rdx, len        ; 字节数
    syscall
challenge icon

挑战

给你一个名为 greeting 的字符串,其值为 'Hi',后面跟着一个换行符。写出将 greeting 的地址加载到 rsi 的代码行。

只写用于 rsi 的 mov 指令。

亲手试试

section .text
    global _start

_start:
    %include "solution.asm"
    
    mov rax, 1
    mov rdi, 1
    ; rsi 已经存有地址(来自你的代码)
    mov rdx, greetingLen
    syscall

    mov rax, 60
    mov rdi, 0
    syscall
quiz icon自我测试

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

基础知识中的所有课

自己练习: Assembly 在线编辑器