NASM汇编教程翻译07 第七讲 换行符

英文原版地址:NASM Assembly Language Tutorials - asmtutor.com

对于像”Hello world“这样的命令行程序,换行符时必不可少的。一旦我们开始构建要求用户输入的程序,它们变得更重要。但是换行符维护起来可能会变得麻烦。有时想在字符串包含它们,有时也想删去它们。如果你继续通过在声明消息文本后添加 0AH 的方式在你的变量中硬编码换行符,它将变成一个问题。如果这是代码中一处我们不想输出这个变量的换行符的地方,需要去写一些额外逻辑在运行时从字符串中删去。

如果我们写一个子程序输出我们的消息后打印一个换行符,对于程序的维护性是有好处的。这样,当我们需要换行符时调用这个子程序,不需要时就调用现在的sprint子程序。

调用 sys_write 需要我们传递指向想输出的字符串在内存中地址的指针,所以我们不能只传一个换行符给我们的打印函数。我们也不想仅为了保存换行符去创建另一个变量,所以用栈来代替。

这个方法是通过将换行符移到EAX寄存器中运作的。我们将EAX压到栈上然后通过扩展栈指针寄存器ESP获取地址。ESP是另一个寄存器。当ESP指向一个字符在内存中的地址,sys_write将被允许使用它去打印。

functions.asm文件

;------------------------------------------
; int slen(String message)
; 字符串长度计算函数
slen:
    push    ebx
    mov     ebx, eax
 
nextchar:
    cmp     byte [eax], 0
    jz      finished
    inc     eax
    jmp     nextchar
 
finished:
    sub     eax, ebx
    pop     ebx
    ret
 
;------------------------------------------
; void sprint(String message)
; 字符串打印函数
sprint:
    push    edx
    push    ecx
    push    ebx
    push    eax
    call    slen
 
    mov     edx, eax
    pop     eax
 
    mov     ecx, eax
    mov     ebx, 1
    mov     eax, 4
    int     80h
 
    pop     ebx
    pop     ecx
    pop     edx
    ret
 
;------------------------------------------
; void sprintLF(String message)
; 打印字符串和换行符函数
sprintLF:
    call    sprint
 
    push    eax         ; 当我们在这个函数中使用EAX时通过将EAX压入栈来进行保护
    mov     eax, 0AH    ; 将0AH移到EAX中 - 0AH是换行符的ascii码
    push    eax         ; 将换行符放到栈上,以便我们获取地址
    mov     eax, esp    ; 将当前栈指针的地址放到EAX寄存器中给sprint函数
    call    sprint      ; 调用sprint函数
    pop     eax         ; 从栈上移除换行符
    pop     eax         ; 恢复调用函数前EAX原本的值
    ret                 ; 返回程序
 
;------------------------------------------
; void exit()
; 退出程序并复原资源
quit:
    mov     ebx, 0
    mov     eax, 1
    int     80h
    ret

hello.asm文件

%include        'functions.asm'                             ; 包含我们的外部文件
 
SECTION .data
msg1    db      'Hello, brave new world!', 0h               ; 注:已经移除了换行符
msg2    db      'This is how we recycle in NASM.', 0h       ; 注:已经移除了换行符
 
SECTION .text
global  _start
 
_start:
 
    mov     eax, msg1       ; 将第一个字符串的地址给EAX
    call    sprintLF        ; 注:调用带有换行符的字符串打印函数
 
    mov     eax, msg2       ; 将第二个字符串的地址给EAX
    call    sprintLF        ; 注:调用带有换行符的字符串打印函数
 
    call    quit            ; 调用退出函数

编译命令

nasm -f elf hello.asm

链接命令

ld -m elf_i386 hello.o -o hello

执行命令

./hello

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值