<分区>
我正在学习 NASM 汇编器,但目前我一直在处理换行符。
如何打印换行符?我会给你看。但是,在我展示它之前,重要的是向您介绍一下我的平台:
$ uname -a
Linux 4.4.0-97-generic #120-Ubuntu SMP Tue Sep 19 17:28:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -a
No LSB modules are available.
Distributor ID : Ubuntu
Description : Ubuntu 16.04.3 LTS
Release : 16.04
Codename : xenial
我为学习准备的函数:
sprint:
push rdx
push rbx
push rax
push rcx
mov rax, rcx
pop rcx
jmp next_char
ret
sprint_syscall:
mov rbx, 1
mov rax, 4
int 80h
pop rax
pop rbx
pop rdx
ret
sprint_linefeed:
call sprint
push rcx
mov rcx, 0Ah
push rcx
mov rcx, rsp
call sprint
pop rcx
pop rcx
ret
next_char:
cmp byte [rax], 0
jz count_length
inc rax
jmp next_char
count_length:
sub rax, rcx
mov rdx, rax
jmp sprint_syscall
quit:
push rbx
push rax
mov rbx, 0
mov rax, 1
int 80h
pop rax
pop rbx
ret
主应用程序,可能会使用给定的功能之一:
%include 'functions.asm'
SECTION .data
msgFirst db "Hello World!", 0h
msgSecond db "Another string.", 0h
SECTION .text
global _start
_start:
mov rcx, msgFirst
call sprint_linefeed
mov rcx, msgSecond
call sprint_linefeed
call quit
所有编译都很好并且工作得很好。如果要编译/链接:
nasm -g -f elf64 -l main.lst main.asm -o main.o && ld main.o -o main
然后执行编译好的app,我们可以看到:
Hello World!Another string
如您所见,没有任何换行符,尽管调用了 sprint_linefeed
函数,该函数使用下一条指令打印换行符:
sprint_linefeed:
call sprint
push rcx ; push rcx onto the stack to preserve it
mov rcx, 0Ah ; move 0Ah into rcx, 0Ah is the ASCII char for a linefeed
push rcx ; push the linefeed char onto the stack
mov rcx, rsp ; move the address of the pointer into rcx for the 'sys_write' syscall
call sprint
pop rcx ; remove the linefeed char from the stack
pop rcx ; restore the original value of rcx
ret
因此,对我的操作的解释是指 sprint()
调用给定的字符串,然后将 0Ah
字符压入堆栈。稍后,我从 RSP 寄存器获取指针以再次调用 sprint()
函数。
它已完成,因为 SYS_WRITE
系统调用需要指针来打印给定字符串 ( http://fresh.flatassembler.net/lscr/data/004.html)。
如果将 OAh
字符添加到字符串声明中:
SECTION .data
msgFirst db "Hello World!", 0Ah, 0h
调用相同的函数,但使用不同的字符串值,给了我们等待的结果,但这没有意义,因为 sprint_linefeed()
被定义为传递冗余 ASCII 字符的声明.
我应该在我的源代码中修复什么才能使 sprint_linefeed()
正常工作?