在组装NASM ELF64世界中迷失了

时间:2012-11-30 05:07:58

标签: linux assembly 64-bit nasm

因此,作为我的计算机体系结构课程的一部分,我需要对Assembly感到满意,或者至少足够舒服,我正在尝试读取用户的输入然后重新打印它(暂时),这是我的我是如何尝试用伪代码解决这个问题的:

  1. 声明msg变量(这将在屏幕上打印)
  2. 使用足够长的值声明长度变量(由sys_write函数使用)
  3. 弹出堆栈以获取程序名称
  4. 再次弹出堆栈以获取第一个参数
  5. 将堆栈的当前值移动到msg变量
  6. 将消息移至ECX(sys_write参数)
  7. 将长度移至EDX(sys_write参数)
  8. 使用标准输出
  9. 调用sys_write
  10. 内核通话
  11. 调用sys_exit并离开
  12. 这是我目前的代码

    section .data
      msg:    db 'placeholder text',0xa;
      length: dw 0x123;
    
    section .text
      global _start 
    
        _start: 
          pop rbx;
          pop rbx;
          ; this is not working when I leave it in I get this error:
          ; invalid combination of opcode and operands                                                                                            
          ;mov msg, rbx;
          mov ecx, msg;
          mov edx, length;
    
          mov eax, 4;
          mov ebx, 1;
          int 0x80;
          mov ebx, 0;
          mov eax, 1;
          int 0x80;
    

    当我把它遗漏(没有将参数移到msg中)时,我得到了这个输出

    placeholder text
    #.shstrtab.text.data
                         �@�$�`��
    

    我们真的刚刚开始使用NASM,所以我将非常感谢任何帮助,我一直在考虑这个http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html#stackhttp://syscalls.kernelgrok.com/根据我的理解来调整注册表名称的示例http://www.nasm.us/doc/nasmdo11.html

    我正在运行Ubuntu 12.04,64位编译(甚至不确定这是否是正确的词)在ELF64下的NASM,我很抱歉问这么愚蠢的问题,但我一直无法为NASM找到一个足够简单的教程使用64位。

3 个答案:

答案 0 :(得分:4)

调用程序时,堆栈应如下所示:

+----------------+
| ...            | <--- rsp + 24
+----------------+
| argument 2     | <--- rsp + 16
+----------------+
| argument 1     | <--- rsp + 8
+----------------+
| argument count | <--- rsp
+----------------+

第一个参数是程序的名称,第二个参数是用户输入(如果用户输入任何内容作为参数)。因此参数的计数至少为1.

64-模式下系统调用的参数存储在以下寄存器中:

  • rax(系统电话号码)
  • rdi(第一个参数)
  • rsi(第二个论点)
  • rdx(第三个参数)
  • rcx(第四个参数)
  • r8(第五个论点)
  • r9(第六个论点)

使用syscall调用系统调用。可以找到所有系统调用的数量 here here(是的,它们与32位模式下的数字不同)。

这是应该做你的事情的程序:

section .data
    msg:    db 'Requesting 1 argument!', 10  ; message + newline

section .text
    global  _start

_start:
    cmp     qword [rsp], 2    ; check if argument count is 2
    jne     fail              ; if not jump to the fail lable

    mov     rax, 1            ; sys_write
    mov     rdi, 1            ; stdout
    mov     rsi, [rsp+16]     ; get the address of the argument 
    mov     rdx, 1            ; one character (length 1)

loop:
    cmp     byte [rsi], 0     ; check if current character is 0
    je      exit              ; if 0 then jump to the exit lable
    syscall
    inc     rsi               ; jump to the next character
    jmp     loop              ; repeat

fail:
    mov     rax, 1            ; sys_write
    mov     rdi, 1            ; stdout
    lea     rsi, [rel msg]    ; move the address of the lable msg in rsi
    mov     rdx, 23           ; length = 23
    syscall

exit:
    mov     rax, 60           ; sys_exit
    mov     rdi, 0            ; with code 0
    syscall

由于代码在许多方面并不完美,您可能需要修改它。

答案 1 :(得分:2)

你完全按照说明进行操作 - 这是预期的输出。

您写入消息的堆栈变量只是一些二进制值 - 确切地说,它是指向包含命令行参数的字符串数组的指针。 要理解这一点,要么必须打印这些字符串,要么将指针转换为ascii字符串,例如。 “0x12313132”。

答案 2 :(得分:2)

我的操作系统是64位的Ubuntu。编译代码会产生错误:

nasm print3.asm 

print3.asm:12: error: instruction not supported in 16-bit mode
print3.asm:13: error: instruction not supported in 16-bit mode

&#34; pop rbx&#34;位于。

添加&#34; BITS 64&#34;到asm文件的顶部解决了问题:

BITS 64

section .data
  msg:    db 'placeholder text',0xa;
  length: dw 0x123;

...