assembly NASM附加到字符串,紧接着

bmvo0sr5  于 2023-02-23  发布在  其他
关注(0)|答案(1)|浏览(90)

对于上下文,我在64位Debian发行版上使用NASM。
我还在学习汇编语言,这是我编写自己的编程语言的一部分,但最近我遇到了一个问题,我不知道如何处理。以下是我的编译器吐出的代码片段:

section .text
global _start
section .var_1 write
    char_1 db 'Q', 0
section .var_2 write
    string_1 db 'Asdf', 0
section .var_3 write
    char_2 db 'W', 0
section .text
_start:
push 4 ; String length onto stack
push string_1
;; Push a raw char onto the stack
mov bl, [char_1]
push bx
pop ax
pop rbx
pop rcx
mov byte [rbx+rcx], al

如果我输出string_1的值,我看到的是AsdfWQ。这是因为我使用了mov命令来进行追加,再加上我在字符串的终止字符后声明了一些数据,我一直在Google上搜索,但没有找到解决这个问题的方法(部分原因是我不知道到底要搜索什么)。从概念上讲,我认为我可以将string_1之后的所有内容的地址移动我所附加内容的长度偏移量,但如果在此之后有40个不同的数据片段,这似乎效率非常低。我试图解决的问题是,如何管理程序集中大小可能增加或减少的动态数据?

    • 编辑**

感谢fuz指出通过brk调用进行动态内存分配是可行的,我对程序做了一些修改,但仍然遇到了一些问题:

section .var_1 write                                                                                                                                                                           
    hello_string db '', 0                                                                                                                                                                      
section .var_2 write                                                                                                                                                                           
    again_string db 'Again!', 0                                                                                                                                                                
section .text                                                                                                                                                                                  
    _start:                                                                                                                                                                                    
                                                                                                                                                                                               
    ;; Get current break address                                                                                                                                                               
    mov rdi, 0                                                                                                                                                                                 
    mov rax, 12                                                                                                                                                                                
    syscall                                                                                                                                                                                    
                                                                                                                                                                                               
    ;; Attempt to allocate 8 bytes for string                                                                                                                                                  
    mov rdi, rax                                                                                                                                                                               
    add rdi, 8                                                                                                                                                                                 
    mov rax, 12                                                                                                                                                                                
    syscall                                                                                                                                                                                    
                                                                                                                                                                                               
    ;; Set the memory address to some label                                                                                                                                                    
    mov qword [hello_string], rax                                                                                                                                                              
                                                                                                                                                                                               
    ;; Try declaring a string                                                                                                                                                                  
    mov byte [hello_string], 'H'                                                                                                                                                               
    mov byte [hello_string+1], 'e'                                                                                                                                                             
    mov byte [hello_string+2], 'l'                                                                                                                                                             
    mov byte [hello_string+3], 'l'
    mov byte [hello_string+4], 'o'
    mov byte [hello_string+5], ','
    mov byte [hello_string+6], ' '
    mov byte [hello_string+7], 0
    ;; Print the string
    mov rsi, hello_string
    mov rax, 1
    mov rdx, 8
    mov rdi, 1
    syscall
    ;; Print the other string
    mov rsi, again_string
    mov rax, 1
    mov rdx, 5
    mov rdi, 1
    syscall

这将导致Hello, ello,,这意味着我仍在覆盖与again_string标签相关的数据?但我的印象是,使用brk进行分配将在数据初始化后进行?

bejyjqdl

bejyjqdl1#

完全归功于用户fuz,他通过一个周末的几篇评论,帮助橡皮鸭调试正在发生的事情,同时教育了我。
事实证明,不知道指针真的伤害了我对这里的理解。使用brk并将一段数据(如字符串)赋给标签的方法是:

section .var_1 write                                                                                                                                                                           
    hello_string dq 0                                                                                                                                                                     
section .var_2 write                                                                                                                                                                           
    again_string db 'Again!', 0                                                                                                                                                                
section .text                                                                                                                                                                                  
    _start:                                                                                                                                                                                    
                                                                                                                                                                                               
    ;; Get current break address                                                                                                                                                               
    mov rdi, 0                                                                                                                                                                                 
    mov rax, 12                                                                                                                                                                                
    syscall                                                                                                                                                                                    
                                                                                                                                                                                               
    ;; Attempt to allocate 8 bytes for string                                                                                                                                                  
    mov rdi, rax                                                                                                                                                                               
    add rdi, 8                                                                                                                                                                                 
    mov rax, 12                                                                                                                                                                                
    syscall                                                                                                                                                                                    
                                                                                                                                                                                               
    ;; Set the memory address to some label                                                                                                                                                    
    mov qword [hello_string], rax                                                                                                                                                              
                                                                                                                                                                                               
    ;; Try declaring a string                                                                                                                                                                  
    mov byte [hello_string], 'H'                                                                                                                                                               
    mov byte [hello_string+1], 'e'                                                                                                                                                             
    mov byte [hello_string+2], 'l'                                                                                                                                                             
    ...

这个解决方案与打印Hello, ello!的编辑过的问题代码片段之间的主要区别在于标签的声明,当使用hello_string dq 0时,这允许我存储rax的内存地址,这是我分配的8字节内存的起点,然后从那里追加到8个字节。当我使用hello_string db '', 0然后声明另一个字符串时,我只能存储一个字节,当我获得声明内存的入口点时,这个字节似乎不足以存储rax的内存地址。

相关问题