# 目的: 读取一个文件的内容到buffer
.intel_syntax noprefix
.equ SYSEXIT, 0x3c
.equ SYSREAD, 0
.equ SYSOPEN, 2
# 打开文件的选项见/usr/include/asm-generic/fcntl.h, 允许选项叠加
.equ O_RDONLY, 0
.equ BUFFER_SIZE, 500
.section .bss
.lcomm BUFFER_DATA, BUFFER_SIZE
.section .text
# 栈位置
.equ ST_SIZE_RESERVE, 8 # 描述fd大小
.equ ST_FD_IN, -8
.equ ST_FD_OUT, -16
.equ ST_ARGC, 0 # 参数个数
.equ ST_ARGV_0, 8 # 程序名
.equ ST_ARGV_1, 16 # 输入文件名
.equ ST_ARGV_2, 24 # 输出文件名
.globl _start
_start:
mov rbp, rsp
# linux开始时, 所有指向命令行参数的指针都存储在栈中, 参数个数在[rsp], 程序名在[rsp+8], 参数在[rsp+16]及之后的存储位置, 指针指向的字符串参数以``结尾.
open_files: # symbol不影响代码程序运行, 仅在程序跳转时有用
open_fd_in: # 打开文件, 会将fd结果放入rax
mov rax, SYSOPEN
mov rdi, QWORD PTR [rbp+ST_ARGV_1] # 获取输入文件名
mov rsi, O_RDONLY # 打开选项
mov rdx, 0 # 权限, 不影响实际的读操作
syscall
push rax # 保存输入文件的fd
read_loop_begin: # 开始读取文件
mov rax, SYSREAD
mov rdi, QWORD PTR [rbp+ST_FD_IN] # rbx放入fd
mov rsi, BUFFER_DATA # rsi保存缓冲区地址
mov rdx, BUFFER_SIZE # rdx保存缓冲区大小
syscall
mov rdi, rax
mov rax, SYSEXIT # 退出
syscall
运行:
$ as --64 s.s -o a.o
$ ld a.o
$ gdb --args ./a.out in.txt // in.txt有12个ascii
(gdb) b _start
Breakpoint 1 at 0x401000
(gdb) r
Starting program: /home/chen/git/learn_asm/example/s.out 5.in.txt
Breakpoint 1, 0x0000000000401000 in _start ()
(gdb) si 12
0x000000000040103b in read_loop_begin ()
(gdb) disassemble // att语法
Dump of assembler code for function read_loop_begin:
0x000000000040101f <+0>: mov $0x0,%rax
0x0000000000401026 <+7>: mov -0x8(%rbp),%rdi
0x000000000040102a <+11>: mov 0x402000,%rsi
0x0000000000401032 <+19>: mov $0x1f4,%rdx
0x0000000000401039 <+26>: syscall
=> 0x000000000040103b <+28>: mov %rax,%rdi
0x000000000040103e <+31>: mov $0x3c,%rax
0x0000000000401045 <+38>: syscall
End of assembler dump.
(gdb) p /x $rsi
$1 = 0x0
实际读取结果不对, 调试发现: mov rsi, BUFFER_DATA
被编译成了 mov 0x402000,%rsi
, 此时rsi是0, 因为取的是BUFFER_DATA(0x402000)头8B的内容, 请问要引用BUFFER_DATA得怎么写?