gpt4 book ai didi

gcc - 如何用gcc生成可以用nasm编译的汇编代码

转载 作者:行者123 更新时间:2023-12-04 10:48:32 33 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





How to generate a nasm compilable assembly code from c source code on Linux?

(3 个回答)


8 个月前关闭。




我想把学习汇编语言作为一种爱好,我经常使用 gcc -S生产 assembly 输出。这非常简单,但我无法编译程序集输出。我只是好奇这是否可以做到。我尝试使用 -masm=intel 使用标准汇编输出和英特尔语法。 .两者都不能用 nasm 编译并与 ld 链接.

所以我想问一下是否可以生成汇编代码,然后可以编译。

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

 >> 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 得到的输出是:
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 的输出。

编辑 :

我得到了一个 hint我的问题在另一个问题中得到解决;不幸的是,在测试了那里描述的方法后,我无法生成 nasm汇编格式。您可以看到 objconv 的输出以下。
所以我仍然需要你的帮助。
>>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 的输出时出错了.我应该跑:
sed -i "s/align=1//g ; s/[a-z]*execute//g ; s/: *function//g;  /default *rel/d" csimp.asm

所有步骤都可以浓缩在 bash 中脚本
#! /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警告:
 ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080 

以这种方式生成的可执行文件因段错误消息而崩溃。我会很感激你的帮助。

最佳答案

我认为您遇到入口点错误的困难是尝试使用 ld在包含名为 main 的入口点的目标文件上而 ld正在寻找名为 _start 的入口点.

有几个考虑因素。首先,如果您为了使用 printf 之类的函数而与 C 库链接。 ,链接将期望 main作为入口点,但如果您不与 C 库链接,ld将期待 _start .您的脚本非常接近,但是您需要某种方式来区分您需要哪个入口点来完全自动化任何源文件的过程。

例如,以下是使用您的源文件方法的转换,包括 printf .它被转换为 nasm使用 objconv如下:

生成目标文件:

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

用objconv转换成nasm格式的汇编文件
objconv -fnasm s3.obj

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

使用您的 sed 的稍微修改版本调用,调整内容:
sed -i -e 's/align=1//g' -e 's/[a-z]*execute//g' -e \
's/: *function//g' -e '/default *rel/d' s3.asm

(注意:如果没有标准库函数,并使用 ld ,将 main 更改为 _start 将以下表达式添加到您的 sed 调用中)
-e 's/^main/_start/' -e 's/[ ]main[ ]*.*$/ _start/'

(可能有更优雅的表达方式,这只是举例)

编译 nasm (替换原始目标文件):
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

关于gcc - 如何用gcc生成可以用nasm编译的汇编代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35102193/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com