如何在使用gcc工具的汇编程序构建中接受来自命令行的输入? [英] how to accept input from command line in a assembly program build using gcc tools?

查看:129
本文介绍了如何在使用gcc工具的汇编程序构建中接受来自命令行的输入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实际上想在assembly(linux)中编写一个程序,以从命令行接受文件名,当我使用"ld"命令进行构建时,我成功通过使用连续的弹出操作码从堆栈中检索值而成功,但是当我使用"gcc"命令时不成功.我需要使用gcc,因为我将在此程序中使用各种C std库函数.

I actually wanted to write a program in assembly(linux) , to accept filename from the command line and I was successful by retrieving the values from the stack using successive pop opcodes when I used "ld" command to build but I was unsuccessful when i used "gcc" command . I need to use gcc because I will be using various C std library function in this program.

实际上该文件正在创建中,但是它始终带有无效编码"标签,并在目录中显示为<? G ?.我想知道:

Actually the file was creating , but its always got a "Invalid encoding " label and appeared like <? G ? in the directory.I wanted to know:

  1. 使用gcc工具进行构建时,我们是否遵循不同的程序
  2. 出于好奇的原因,创建无效的编码文件的可能原因是什么.

以下是适用于ld的示例代码,但不适用于gcc.

Here is a sample code that works with ld but not with gcc.

section .data
    filename: db 'testing',0
section .text
    ;extern printf    ;to be uncommented when using gcc
    ;extern scanf     ;           -do-
    global _start   ; replace with main when using gcc

_start:     ; replace with main:
    pop ebx     ; argc (argument count)
    pop ebx     ; argv[0] (argument 0, the program name)
    pop ebx     ; The first real arg, a filename

    mov eax,8       
    ; issue: ebx is not holding the filename popped from cli using gcc 
    ;mov     ebx,filename   ; filename as a constant works with gcc but cli?
    mov ecx,00644Q  ; Read/write permissions in octal (rw_rw_rw_)
    int 80h     ; Call the kernel
                ; Now we have a file descriptor in eax

    test    eax,eax     ; Lets make sure the file descriptor is valid
    js  terminate   ; If the file descriptor has the sign flag              
    call    fileWrite

terminate:
    mov ebx,eax     ; If there was an error, save the errno in ebx
    mov eax,1       ; Put the exit syscall number in eax
    int 80h     ; control over to kernel

fileWrite:  ; simply closing the file for time being
    mov ebx,eax        ; edited
    mov eax,6       ; sys_close (ebx already contains file descriptor)
    int 80h
    call terminate

解决方案和注意事项: 使用libc或裸骨程序集时,堆栈有所不同.

Solution and Caveat: There is a difference in the stack when using libc or bare-bone assembly.

  1. 使用libc时,第一个弹出窗口将返回返回地址,并分别返回argc和argv值.

  1. When using libc the , the first pop returns the return address followed by argc and argv values respectively.

在准系统中,第一个pop返回argc,因此每个pop都给出了连续的argv值,这与使用libc时返回的参数指针不同.

In bare-bone assembly , the first pop return the argc ,and every pop hence gives the successive argv values unlike a arguments pointer returned when using libc.

来源: 通过x86汇编从argv中读取文件名

推荐答案

此博客文章介绍了在调用程序的入口点时堆栈的外观:

This blog post explains how the stack looks like when the entry point of a program is being called: http://eli.thegreenplace.net/2012/08/13/how-statically-linked-programs-run-on-linux

简而言之,您可以在堆栈中包含以下元素:

In a nutshell, you have these elements on the stack:

  1. argc
  2. argv[0]-程序/可执行名称
  3. argv[1] ... argv[argc-1]-程序参数
  4. argv[argc]-始终为NULL
  5. envp[0] ... envp[N]-当前环境
  6. NULL终止envp数组
  1. argc
  2. argv[0] - program/executable name
  3. argv[1] ... argv[argc-1] - Program arguments
  4. argv[argc] - Always NULL
  5. envp[0] ... envp[N] - The current environment
  6. NULL to terminate the envp array

这些指针是32位还是64位,具体取决于您的内核. x86 = 32位,x64 = 64位.因此,请确保从堆栈中获取正确的大小.在x64上,argc占用8个字节.

Those pointers are either 32 bit or 64 bit, depending on your kernel. x86 = 32 bit, x64 = 64 bit. So make sure you fetch the correct sizes from the stack. On x64, argc takes 8 bytes.

如果要避免这种麻烦,请链接libc并提供main入口点而不是_start. libc包含_start,它将把命令行参数处理为数组,然后使用堆栈中的三个元素调用main:

If you want to avoid this hassle, link against libc and provide a main entry point instead of _start. libc contains _start which will process the command line argument into arrays and then call main with three elements on the stack:

  1. int argc
  2. char** argv
  3. char** envp
  1. int argc
  2. char** argv
  3. char** envp

libc的启动代码也将初始化stdio框架;否则,由于stdout将是NULL指针,因此对printf()的调用将失败.

The startup code of libc will also initialize the stdio framework; without that, calls to printf() will fail because stdout will be a NULL pointer.

这篇关于如何在使用gcc工具的汇编程序构建中接受来自命令行的输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆