私はNASM構文(ああ、これはもう一度ではない、、あなたはすべて考えている)でx86 Linuxアセンブリを学んでいる。私は単にEAXの値をstdoutに出力するサブルーチンを作ろうとしています。コードは実行され、エラーなく終了しますが、何も印刷されません。なぜ私は理解できません。これは、この(私は抜本的な何かが欠けている場合を除き、これは、おそらく無関係である)のように見える私のメインファイルから呼び出されLinux x86 NASM - サブルーチン:EAXからdwordを出力
segment .bss
to_print: resd 1
segment .text
global print_eax_val
print_eax_val: ; (top)
push dword ebx ;Stack: edx
push dword ecx ; ecx
push dword edx ; ebx
; (bot)
mov ecx,eax ;ecx = eax
mov [to_print],ecx ;to_print = ecx
mov eax, 4 ;sys_write
mov ebx, 1 ;to stdout
add ecx, 47 ;add 47 for ASCII numbers
mov edx, 2 ;double word = 2 bytes
int 0x80
mov eax, [to_print] ;eax = original val
pop edx ;pop the registers back from the stack
pop ecx
pop ebx ;Stack: empty
ret
:まず第一に、ここで私が働いているファイルです。
segment .data
hello db "Hello world!", 0
newline db 0xA
len equ $ - hello
len2 equ $ - newline
segment .text
extern print_nl
extern print_eax_val
global main
main:
enter 0,0
call print_nl
mov eax, 1
call print_eax_val
mov ebx, 0 ;exit code = 0 (normal)
mov eax, 1 ;exit command
int 0x80 ;ask kernel to quit
print_nl
は、改行を定義して印刷する別のサブルーチンです。これは正常に実行され、期待どおりに新しい行が印刷されます。
問題は私のsys_write
コールの長さパラメータと関係がありますか?私はresd 1
と予約したEAX
とto_print
の両方のラベルのサイズであるdword
のサイズである2を与えています。私は絶望から1,4,8,16,32までの長さを変えようとしました...何も働いていませんでした。
EDIT:不思議に思っている人のため、ここでは、私は、コードを固定する方法である:(Iは私が変更された行にアスタリスクを入れます):
segment .bss
to_print: resd 1
segment .text
global print_eax_val
print_eax_val: ; (top)
push dword ebx ;Stack: edx
push dword ecx ; ecx
push dword edx ; ebx
; (bot)
mov ecx,eax ;ecx = eax
mov [to_print],ecx ;to_print = ecx
**** add dword [to_print], 48
mov eax, 4 ;sys_write
mov ebx, 1 ;to stdout
**** mov ecx, to_print
mov edx, 2
int 0x80
**** sub dword [to_print], 48
mov eax, [to_print] ;eax = original val
pop edx ;pop the registers back from the stack
pop ecx
pop ebx ;Stack: empty
ret
基本的には、ecx
はアドレスが含まれている必要があり値を指定するのではなく、印刷するブロックの値を指定します。選択された答えに指摘されているように、のみが0〜9の範囲で動作します。
EDIT 2:sys_write(edx
に格納されているもの)の2番目のパラメータについて少し混乱しました。私はそれが単にバイト数を指していると思う。したがって、dword
の場合、私が使用していたように、ダブルワードが4バイトまたは32ビットであるため、4を使用するのが適切です。私はそれがx86がリトルエンディアンであるために動作していると思います。だから、メモリ内で、to_print
の六角値は次のようになります。
90 00 00 00
そして2の付属の長さと、SYS_WRITEを取得します。
90 00
をだから、値が運よくありません堕落する。私はto_print
に上記の値を与えるつもりはない知っているので
私は後でresb 1
を使用して、代わりにバイトとしてto_print
を格納するためのコードを変更し、byte
代わりのdword
を使用してアクセスする...バイトは、ここで結構です9.
ありがとうございました!あなたの答えはとても役に立ちました。ええ、私はこれが0から9の間だけ働くことを理解します、私はちょうど基本のいくつかを落とそうとしています。たぶん私はいくつかの配列/ポインターint to文字列のビジネスから始まるだろう。私は、更新されたコードで自分の投稿を編集し、知りたい人は誰でも編集します。 –
私はアセンブリ言語に取り組んであなたに拍手し、あなたが幸運を祈ります。ところで、あなたの質問は、プロトタイプ良いSOの質問です。あなたは正確に必要な情報を与え、あなたが試したことを示し、特定の質問をしました。 +1 –
もう一度おねがいします。私は確かにあなたの答えを「プロトタイプのよいSO」答えとして分類します。私が取り組んでいるプロジェクトでは、巨大なC++のsegfault/pointer meltdownの後でいくつかのx86アセンブリを学ぶことにしました。まず第一に、それは素敵な転換です。第二に、コードを書くときに私が実際にやっていることを知りたいのです。 –