2008/05/20

[assembler] 64bit アセンブラで Hello World!

Gas

Forth をいじってるとどんどん低レベルの領域に興味が移っていく。gas を使って Hello World! 64bit バージョン。.code64 で 64bit 指定だと思う。。。32bit だと %eax とか書くレジスタを %rax と書く。

/* -*- mode: asm; coding: utf-8; -*-
as -o hello64.o hello64.s
ld -o hello64 hello64.o
./hello64
*/

.code64
.text

.global _start

_start:
mov $4, %rax # 出力システムコール
mov $1, %rbx # 標準出力
mov $msg, %rcx # 文字列のアドレス
mov $len, %rdx # 文字列の長さ
int $0x80 # システムコール実行

mov $1, %rax # exit システムコール
mov $0, %rbx # exit コード
int $0x80 # システムコール実行

.data

msg: .ascii "Hello World!\nまみむめも♪\n"
msgend: len = msgend - msg

NASM でも

;; -*- mode: asm; coding: utf-8; -*-
;; nasm -f elf64 nasm.asm
;; ld -s -o nasm nasm.o
;; ./nasm

section .text

global _start

_start:
mov rax, 4 ; 出力システムコール
mov rbx, 1 ; 標準出力
mov rcx, msg ; 文字列のアドレス
mov rdx, len ; 文字列の長さ
int 80h ; システムコール実行

mov rax, 1 ; exit システムコール
mov rbx, 0 ; exit コード
int 80h ; システムコール実行

section .data

msg db 'Hello World!', 0ah, 'まみむめも♪', 0ah
len equ $ -msg

6 件のコメント:

Jeff さんのコメント...

Using int 80 directly is not a good idea as you constrain your program to only work on certain kernel versions if the interface changes.

Instead:

;; nasm -f elf64 eat.asm && gcc eat.asm -o eat && rm eat.o
;;
[SECTION .text]
global main
extern puts
main:
mov edi, msg
call puts
mov rax, 0
ret
[SECTION .data]
msg db "Eat at Joe's!",0
[SECTION .bss]

Yoshinori Tahara さんのコメント...

Thank you for your comment, jeff.
I tried
push msg
call puts
and failed.
Your comment is helpful.

Jeff さんのコメント...

Yes, "push msg, call puts" is the correct "calling convention" for 32bit ABI

In 64bit, due to availability of additional registers the ABI is changed to first pass up to 6 parameters to a function using registers.

So you see in my example, I mov the msg to edi (first parameter register)

Here is an overview of register usage in calling convetion for 64bit linux:

linux 64bit regs

%rax Return value
%rbx Callee saved
%rcx 4th argument
%rdx 3rd argument
%rsi 2nd argument
%rdi 1st argument
%rbp Callee saved
%rsp Stack pointer
%r8 5th argument
%r9 6th argument
%r10 Callee saved
%r11 Used for linking
%r12 Unused for C
%r13 Callee saved
%r14 Callee saved
%r15 Callee saved


Note that when you compile a C program and examine assembly output, you may see int 80 calls but that is ok because the magic numbers are maintained in glibc.


Jeff

Jeff さんのコメント...
このコメントは投稿者によって削除されました。
Jeff さんのコメント...

These two documents may provide more information.

asm64-handout.pdf
x86-64.org abi.pdf

Yoshinori Tahara さんのコメント...

I see that is 32bit ABI.
Thank you for the in-depth explanation.
Those documents are very useful.
Thank you very much, Jeff.