私は趣味としてアセンブリ言語を学ぼうとしていますgcc -S
が、アセンブリ出力の作成によく使用します。これは非常に簡単ですが、アセンブリ出力をコンパイルできません。私はこれがまったくできるかどうかだけ興味がありました。を使用して、標準のアセンブリ出力とIntel構文の両方を使用してみました-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
編集:
私の問題は別の質問で解決されるというヒントが与えられました。残念ながら、そこで説明されている方法をテストした後、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
。
いくつかの考慮事項があります。まず、のような関数を使用するためにCライブラリとリンクしている場合printf
、リンクは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
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加