在x86_64程序集中将一个.data和一个.bss字符串连接在一起

时间:2018-12-06 08:12:13

标签: assembly 64-bit nasm x86-64

我正在编写一个程序,要求您输入姓名,然后像这样打印出来:

<name> is your name?

这是我当前的代码:

section .data
    promptText: db "What is your name: ", 0
    promptTextLength: equ $ - promptText
    secondText: db " is your name?", 0

section .bss
    name resb 15

section .text:
    global _start

_start:

    ; Print prompt message
    mov rax, 1
    mov rdi, 1
    mov rsi, promptText
    mov rdx, promptTextLength
    syscall

    ; Get name
    mov rax, 0
    mov rdi, 0
    mov rsi, name
    mov rdx, 15
    syscall

    ; Somehow concatenate "name" and "secondText"

    ; Print second message
    mov rax, 1
    mov rdi, 1
    mov rsi, nameAndSecondText
    mov rdx, nameAndSecondTextLength
    syscall

    ; Exit 0
    mov rax, 60
    mov rdi, 0
    syscall

因此,几乎要添加namesecondText,然后将它们打印到终端。

但是,

我不想只两次调用SYS_WRITE来打印两个字符串,我需要将namesecondText合并到它们自己的变量中。

谢谢!

对不起,如果我使用了错误的术语,我已经习惯了Python,C等高级语言。

1 个答案:

答案 0 :(得分:0)

您不需要字符串的终止NUL,因为您无需使用检查该字符的函数。

删除section .text:中的冒号。然后,您可以使用GDB调试程序。

我建议将secondText直接附加到输入的名称之后。为此,您必须为变量name保留更多空间。 SYS_READ不会注意到这一点,因此在调用SYS_READ之后,该空间仍为空白。

section .data
    promptText:         db "What is your name: "
    promptTextLength:   equ $ - promptText
    secondText:         db " is your name?", 10
    secondTextLength:   equ $ - secondText

section .bss
    name resb 15 + secondTextLength ; Space for input and appended string

section .text
global _start

_start:

    ; Print prompt message
    mov rax, 1                  ; SYS_WRITE - http://man7.org/linux/man-pages/man2/write.2.html
    mov rdi, 1                  ; fd = STDOUT
    mov rsi, promptText         ; *buf
    mov rdx, promptTextLength   ; Count of bytes to write
    syscall                     ; Call Linux

    ; Get name
    mov rax, 0                  ; SYS_READ - http://man7.org/linux/man-pages/man2/read.2.html
    mov rdi, 0                  ; fd = STDIN
    mov rsi, name               ; *buf
    mov rdx, 15                 ; Max count of bytes to read
    syscall                     ; Call Linux - return EAX = number of bytes read
    dec rax                     ; number of bytes read without ENTER

    ; Append secondText
    mov rsi, secondText         ; *source
    mov rdi, name               ; *dest
    add rdi, rax                ; Set pointer one byte behind the real name
    mov rcx, secondTextLength   ; Count of bytes to copy
    lea rbx, [rax + rcx]        ; Save the total length of the string
    rep movsb                   ; Copy RCX bytes from [RSI] to [RDI]

    ; Print name (input + second message)
    mov rax, 1                  ; SYS_WRITE - http://man7.org/linux/man-pages/man2/write.2.html
    mov rdi, 1                  ; fd = STDOUT
    mov rsi, name               ; *buf
    mov rdx, rbx                ; Count of bytes to write (RBX was saved above)
    syscall                     ; Call Linux

    ; Exit (0)
    mov rax, 60                 ; SYS_EXIT
    mov rdi, 0                  ; Exitcode
    syscall                     ; Call Linux / no return