缓冲区地址(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挑战
给你一个名为 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这节课包含一个小测验。开始学习即可作答,并记录你的进度。
基础知识中的所有课
自己练习: Assembly 在线编辑器