だから私はNASM構文でx86 Linuxアセンブリを学んでいます(ああ、これはもうありません、あなたは皆考えています)。EAX の値を標準出力に単純に出力するサブルーチンを作成しようとしています。コードは実行され、エラーなしで終了しますが、何も出力されません。理由がわかりません。まず、私が作業しているファイルは次のとおりです。
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
呼び出しの長さパラメータに関係していますか? のサイズである 2 を与えています。これは、 で予約したレジスタとラベルdword
の両方のサイズです。必死になって長さを1、4、8、16、32に変更してみました...何もうまくいきませんでした。EAX
to_print
resd 1
編集:疑問に思っている人のために、コードを修正した方法を次に示します:(変更した行にアスタリスクを付けます):
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
を含める必要があります。選択した回答で指摘されているように、これはeax が 0-9 の範囲にある場合にのみ機能します。
編集 2 : sys_write の 2 番目のパラメーター (に格納されているものedx
) について少し混乱しました。バイト数を指しているだけだと思います。したがって、dword
私が使用していた a の場合、ダブルワードは 4 バイトまたは 32 ビットであるため、そこで 4 を使用するのが適切です。x86 はリトルエンディアンなので、うまくいったと思います。したがって、メモリ内では、 の 16 進値は次のto_print
ようになります。
90 00 00 00
長さ 2 を指定すると、sys_write は次のようになります。
90 00
したがって、幸いにも値が破損することはありません。
to_print
後で代わりにバイトとして保存するようにコードを変更し、代わりに... を使用resb 1
してアクセスし、 9 を超える値を与えるつもりはないので、ここではバイトで問題ありません。byte
dword
to_print