代码如下:
segment .text
global _start
_start:
mov rcx, [rsp+16]
dec rdx
.L1:
inc rdx
cmp al, byte [rcx+rdx]
jnz .L1
mov rax, 4
mov rbx, 1
int 0x80
mov rax, 1
mov rbx, 0
int 0x80
它将第二个参数字符串(argv [1])参数的地址移入RCX,将RDX计数字符递增直到'\ 0'并写入STDOUT_FILENO。
当我使用yasm进行编译时,请与ld链接并按以下方式运行可执行文件:
$ ./a.out somechars
预期输出为:
somechars$
($代表终端提示,缺少换行符)
但是相反,我立即看到终端提示,就像我什么也没运行,只是在空命令行中按ENTER键一样。
然后我在源代码中添加了更多行:
segment .data ; NEW
; NEW
deb db "somechars", 0 ; NEW
; NEW
segment .text
global _start
_start:
mov rcx, [rsp+16]
mov rcx, deb ; NEW
dec rdx
.L1:
inc rdx
cmp al, byte [rcx+rdx]
jnz .L1
mov rax, 4
mov rbx, 1
int 0x80
mov rax, 1
mov rbx, 0
int 0x80
效果很好:
$ ./a.out somechars
somechars$
(决定键入相同的命令,尽管可以省略“ somechars”)
这是调试器说的:
(gdb) l
1 segment .data
2
3 deb db "somechars", 0
4
5 segment .text
6
7 global _start
8
9 _start:
10 mov rcx, [rsp+16]
(gdb) b 9
Breakpoint 1 at 0x4000b0: file exp.asm, line 9.
(gdb) run somechars
Starting program: /home/polazhinets_a/work/ll/a.out somechars
Breakpoint 1, _start () at exp.asm:10
10 mov rcx, [rsp+16]
(gdb) ni
11 mov rcx, deb
(gdb) x/10cb $rcx
0x7fffffffe1b7: 115 's' 111 'o' 109 'm' 101 'e' 99 'c' 104 'h' 97 'a' 114 'r'
0x7fffffffe1bf: 115 's' 0 '\000'
(gdb) ni
12 dec rdx
(gdb) x/10cb $rcx
0x6000e8: 115 's' 111 'o' 109 'm' 101 'e' 99 'c' 104 'h' 97 'a' 114 'r'
0x6000f0: 115 's' 0 '\000'
(gdb)
在两个MOV之后,RCX指向的数十个字节的数据数据之间显然没有区别,除了在第一种情况下地址为低(数据段),在第二种情况下为高地址(堆栈段)。>
我知道,如果在某处存在延迟,那么READ和WRITE都不提供任何保证,并且很可能处理0个字节,但是我不是想从0x7fffff0000f8( 真正的原因是什么? 已解决 48位堆栈虚拟地址不适合32位,因此应使用SYSCALL而不是32位INT