如何使用可以用nasm编译的gcc生成汇编代码 [英] How to generate assembly code with gcc that can be compiled with nasm

查看:380
本文介绍了如何使用可以用nasm编译的gcc生成汇编代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将汇编语言作为一种爱好学习,并且经常使用gcc -S来产生汇编输出.这非常简单,但是我无法编译程序集输出.我只是很好奇这是否可以完成.我尝试使用-masm=intel同时使用标准程序集输出和intel语法.两者都不能使用nasm进行编译,也不能使用ld链接.

I am trying to learn assembly language as a hobby and I frequently use gcc -S to produce assembly output. This is pretty much straightforward, but I fail to compile the assembly output. I was just curious whether this can be done at all. I tried using both standard assembly output and intel syntax using the -masm=intel. Both can't be compiled with nasm and linked with ld.

因此,我想问一下是否有可能生成汇编代码,然后可以对其进行编译.

Therefore I would like to ask whether it is possible to generate assembly code, that can be then compiled.

更准确地说,我使用了以下C代码.

To be more precise I used the following C code.

 >> cat csimp.c 
 int main (void){
 int i,j;
   for(i=1;i<21;i++)
     j= i + 100;
  return 0;
  }

使用gcc -S -O0 -masm=intel csimp.c生成的程序集,并尝试使用nasm -f elf64 csimp.s进行编译并使用ld -m elf_x86_64 -s -o test csimp.o进行链接.我从nasm得到的输出为:

Generated assembly with gcc -S -O0 -masm=intel csimp.c and tried to compile with nasm -f elf64 csimp.s and link with ld -m elf_x86_64 -s -o test csimp.o. The output I got from nasm reads:

csimp.s:1: error: attempt to define a local label before any non-local labels
csimp.s:1: error: parser: instruction expected
csimp.s:2: error: attempt to define a local label before any non-local labels
csimp.s:2: error: parser: instruction expected

这很可能是由于汇编语法损坏.我希望我可以解决此问题,而无需手动更正gcc -S

This is most probably due to broken assembly syntax. My hope is that I would be able to fix this without having to manually correct the output of gcc -S

修改:

我得到了

I was given a hint that my problem is solved in another question; unfortunately, after testing the method described there, I was not able to produce nasm assembly format. You can see the output of objconv below. Therefore I still need your help.

>>cat csimp.asm 
; Disassembly of file: csimp.o
; Sat Jan 30 20:17:39 2016
; Mode: 64 bits
; Syntax: YASM/NASM
; Instruction set: 8086, x64

global main:  ; **the ':' should be removed !!!** 


SECTION .text                                           ; section number 1, code

main:   ; Function begin
        push    rbp                                     ; 0000 _ 55
        mov     rbp, rsp                                ; 0001 _ 48: 89. E5
        mov     dword [rbp-4H], 1                       ; 0004 _ C7. 45, FC, 00000001
        jmp     ?_002                                   ; 000B _ EB, 0D

?_001:  mov     eax, dword [rbp-4H]                     ; 000D _ 8B. 45, FC
        add     eax, 100                                ; 0010 _ 83. C0, 64
        mov     dword [rbp-8H], eax                     ; 0013 _ 89. 45, F8
        add     dword [rbp-4H], 1                       ; 0016 _ 83. 45, FC, 01
?_002:  cmp     dword [rbp-4H], 20                      ; 001A _ 83. 7D, FC, 14
        jle     ?_001                                   ; 001E _ 7E, ED
        pop     rbp                                     ; 0020 _ 5D
        ret                                             ; 0021 _ C3
; main End of function


SECTION .data                                           ; section number 2, data


SECTION .bss                                            ; section number 3, bss

明显的解决方案:

清理objconv的输出时我犯了一个错误.我应该跑步:

I made a mistake when cleaning up the output of objconv. I should have run:

sed -i "s/align=1//g ; s/[a-z]*execute//g ; s/: *function//g;  /default *rel/d" csimp.asm

所有步骤都可以在bash脚本中压缩

All steps can be condensed in a bash script

#! /bin/bash

a=$( echo $1 | sed  "s/\.c//" ) # strip the file extension .c

# compile binary with minimal information
gcc -fno-asynchronous-unwind-tables -s -c ${a}.c 

# convert the executable to nasm format
./objconv/objconv -fnasm ${a}.o 

# remove unnecesairy objconv information
sed -i "s/align=1//g ; s/[a-z]*execute//g ; s/: *function//g;  /default *rel/d" ${a}.asm

# run nasm for 64-bit binary

nasm -f elf64 ${a}.asm 

# link --> see comment of MichaelPetch below
ld -m elf_x86_64 -s ${a}.o 

运行此代码,我得到ld警告:

Running this code I get the ld warning:

 ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080 

以这种方式生成的可执行文件因分段错误消息而崩溃.非常感谢您的帮助.

The executable produced in this manner crashes with segmentation fault message. I would appreciate your help.

推荐答案

我认为您遇到入口点错误遇到的困难是试图在包含入口点的对象文件中使用ld ld在寻找名为_start的入口点时命名为main.

The difficulty I think you hit with the entry point error was attempting to use ld on an object file containing the entry point named main while ld was looking for an entry point named _start.

有两个注意事项.首先,如果要使用诸如printf之类的功能与C库链接,则链接将以main作为入口点,但如果不与C库进行链接,则ld将期望为_start .您的脚本非常接近,但是您将需要某种方法来区分完全自动化任何源文件过程所需的入口点.

There are a couple of considerations. First, if you are linking with the C library for the use of functions like printf, linking will expect main as the entry point, but if you are not linking with the C library, ld will expect _start. Your script is very close, but you will need some way to differentiate which entry point you need to fully automate the process for any source file.

例如,以下是使用包含printf的源文件的方法进行的转换.使用objconv将其转换为nasm,如下所示:

For example, the following is a conversion using your approach of a source file including printf. It was converted to nasm using objconv as follows:

生成目标文件:

gcc -fno-asynchronous-unwind-tables -s -c struct_offsetof.c -o s3.obj

使用objconv转换为 nasm 格式的汇编文件

Convert with objconv to nasm format assembly file

objconv -fnasm s3.obj

(注意:我的objconv版本添加了DOS行尾-可能缺少一个选项,我只是通过dos2unix运行了它)

(note: my version of objconv added DOS line endings -- probably an option missed, I just ran it through dos2unix)

使用您的sed调用的稍作修改的版本,调整内容:

Using a slightly modified version of your sed call, tweak the contents:

sed -i -e 's/align=1//g' -e 's/[a-z]*execute//g' -e \
's/: *function//g' -e '/default *rel/d' s3.asm

(注意:如果没有标准库功能,请使用ld,通过将以下表达式添加到sed调用中,将main更改为_start)

(note: if no standard library functions, and using ld, change main to _start by adding the following expressions to your sed call)

-e 's/^main/_start/' -e 's/[ ]main[ ]*.*$/ _start/'

(为此可能有更优雅的表达方式,例如)

(there are probably more elegant expressions for this, this was just for example)

使用nasm进行编译(替换原始目标文件):

Compile with nasm (replacing original object file):

nasm -felf64 -o s3.obj s3.asm

使用gcc链接:

gcc -o s3 s3.obj

测试

$ ./s3

 sizeof test : 40

 myint  : 0  0
 mychar : 4  4
 myptr  : 8  8
 myarr  : 16  16
 myuint : 32  32

这篇关于如何使用可以用nasm编译的gcc生成汇编代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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