【问题标题】:printing integer backwards in assembly for macos x86_64在 macos x86_64 的汇编中向后打印整数
【发布时间】:2022-01-02 16:36:40
【问题描述】:

我正在尝试在 macOS 上的程序集 x86_64 中打印一个整数。我已经知道大约有 3/4 的答案,但我无法解决我的问题。

现在,我很乐意将其向后打印。 所以,这是代码:

section .bss                                                            
  3 number_back                 resb                3                       
  4 number_right                resb                3                       
  5                                                                         
  6 section .text                                                           
  7     global _main                                                        
  8 _main:                                                                  
  9     mov rax, 123                                                        
 10     call _get_backwards                                                 
 11                                                                         
 12     mov rax, 0x2000004                                                  
 13     mov rdi, 1                                                          
 14     mov rsi, number_back                                                
 15     mov rdx, 3                                                          
 16     syscall                                                             
 17                                                                         
 18     mov rax, 0x2000001                                                  
 19     xor rdi, rdi                                                        
 20     syscall                                                             
 21                                                                         
 22 _get_backwards:                                                         
 23     xor rdx, rdx                                                        
 24     mov rcx, 10                                                         
 25     div rcx                                                             
 26     add rdx, 48                                                         
 27     mov [rel number_back], rdx                                          
 28                                                                         
 29 loop:                                                                   
 30     inc number_back                                                     
 31     cmp rax, 0                                                          
 32     jne _get_backwards                                                  
 33     ret                     

说明

  1. mov rax, 123 ;将号码移入 rax 寄存器
  2. 调用 get_backwards 过程
  3. 除法和乘法需要 2 个寄存器,一个用于商,一个用于余数。Xor 余数,所以我摆脱了所有的垃圾
  4. mov into rcx, 10 这样我就可以得到与数字的最后一位对应的余数,在这种情况下为 3
  5. 将 rax 除以 rcx
  6. 获取int的ascii码
  7. 将rdx寄存器的内容移动到指针number_back持有的内存地址中
  8. 这是导致问题的部分。我想做类似 number_back[0] = 3, number_back[1] = 2 ... 之类的事情。我认为将指针增加一个会很有趣,但我不正确。我收到此错误
error: invalid combination of opcode and operands
  1. 如果 rax 为 0,则退出,否则循环

提前谢谢你。

【问题讨论】:

    标签: assembly x86-64 nasm


    【解决方案1】:

    你不能增加一个标签,因为它没有存储在内存中的任何地方,只是一个命名的别名,它将被你分配的内存的地址替换。这样做的方法是有一个额外的寄存器(RBX 现在是免费的)来存储您需要添加到您的地址的偏移量。您的代码的另一个问题是,您会将值的(十)个基本表示形式存储为向后数字中的单词,这将超出您的容量。我猜您正在尝试以“正常”从左到右的方式打印您的号码。如果你想这样做,你应该做的是保留更多空间(3字节=> 8个字符)。

    section .bss                                                            
     number_back                 resb                8; 8 characters                       
     number_right                resb                3   
    section .text
        global _main
        _main:
         mov rax, 123 
         mov rbx, 0                                                       
         call _get_backwards                                                 
                                                                             
         mov rax, 0x2000004                                                  
         mov rdi, 1                                                          
         mov rsi, number_back                                                
         mov rdx, 3                                                          
         syscall                                                             
                                                                             
         mov rax, 0x2000001                                                  
         xor rdi, rdi                                                        
         syscall                                                             
                                                                             
     _get_backwards:                                                         
         xor rdx, rdx                                                        
         mov rcx, 10                                                         
         div rcx                                                             
         add rdx, 48                                                         
         mov [rel number_back + rbx], rdx                                          
                                                                             
     loop:                                                                   
         inc rbx                                                    
         cmp rax, 0                                                          
         jne _get_backwards                                                  
         ret     
    

    应该可以(抱歉,我在这台计算机上没有 nasm 编译器)。

    【讨论】:

    • “你不能增加一个不在寄存器中的值。”不正确。您可以在内存中增加字节、字、双字或 qword 大小的变量。正如inc number_back 所建议的问题,您不能做的是增加标签的地址。因为实际上没有内存间接寻址模式,所以您的答案是正确的;即,地址或地址的位移需要在某个时候在寄存器中。
    • 进一步我相信mov [rel number_back + rbx], rdx 不会做你想做的事。要实际使用 RIP 相对寻址,您需要 lea some64bitreg, [rel number_back] 然后使用 [some64bitreg + rbx] 来寻址缓冲区。
    • @not_here_to_play:在 64 位除法 rdx:rax / rcx 后,您将在 rdx 中得到余数,其中包含 0 到 9 范围内的数字,包括 0 到 9。由于这个限制,低字节寄存器dl 将保持与rdx 相同的值。只需在mov 中只使用dl,以便只存储一个字节。
    • @ecm:你说得对,唯一的RIP-relative寻址模式是[RIP + rel32],不涉及任何其他寄存器。不幸的是,NASM 不会拒绝甚至警告[rel symbol + rbx],而是将其组装到[disp32 + rbx],并为链接器重新定位以填充 32 位绝对地址。 (这当然不适用于 MacOS;MachO64 甚至没有重定位类型,因此它在 nasm -fmacho64 的汇编时失败,而在 Linux 上的链接时 -felf64 如果您尝试链接到 PIE 可执行文件中。)
    • 这个答案还有一个错误,它每次迭代都存储 8 个字节,重叠 7 个。所以它存储到 resb 8 的末尾之后,到后面的 resb 3,以及更大的数字商店也过去了。
    猜你喜欢
    • 2011-10-17
    • 2015-09-16
    • 1970-01-01
    • 2015-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    相关资源
    最近更新 更多