Assembly Language & x86 Low-Level Systems Programming · レッスン

引数と戻り値の受け渡し

レジスターとスタックを利用し、プロシージャに引数を渡して値を返すための一般的な規約を学びます。

レッスン 3/412 ステップ

「引数と戻り値の受け渡し」はCoddyKit上の無料Assembly Language & x86 Low-Level Systems Programmingレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAssembly Language & x86 Low-Level Systems Programming学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Assembly Language & x86 Low-Level Systems Programmingコースには全4レッスンが含まれています。

このレッスンの一部はまだ翻訳されておらず、英語で表示されています。

Intro: Data Flow in Procedures

When you write a procedure (like a function in C), it often needs data to work with, and it might produce a result.

This lesson explores how data, called arguments, is sent into a procedure, and how the procedure sends a return value back out.

Why Pass Data?

Procedures are like mini-programs. To make them useful, they need to communicate with the main program or other procedures.

  • Arguments: Input data for the procedure to process.
  • Return Value: The result produced by the procedure.

Without this communication, procedures would be very limited!

Calling Conventions

To ensure procedures can talk to each other, there are rules called calling conventions.

These rules dictate:

  • How arguments are passed (registers or stack).
  • Which registers a procedure can modify.
  • How return values are transmitted.

We'll look at common ways for x86.

Passing Arguments via Registers

For a small number of arguments, it's efficient to pass them using registers.

A common convention (like System V ABI on Linux) uses specific registers for the first few arguments:

  • RDI (1st argument)
  • RSI (2nd argument)
  • RDX (3rd argument)
  • RCX (4th argument)

For 32-bit (x86), these would be EDI, ESI, etc.

Code: Register Arguments (32-bit)

Here, a procedure _add_two takes two numbers in EBX and ECX (acting as arguments) and returns their sum in EAX.

section .data
    msg db "Sum: ", 0

section .text
    global _start

_add_two:
    ; Arguments: EBX, ECX
    ; Returns: EAX
    mov eax, ebx  ; Move first arg to EAX
    add eax, ecx  ; Add second arg
    ret           ; Return to caller

_start:
    ; Prepare arguments for _add_two
    mov ebx, 5    ; First argument
    mov ecx, 3    ; Second argument
    call _add_two ; Call the procedure

    ; EAX now holds the sum (8)
    ; --- Print result (for demonstration) ---
    ; Convert EAX to ASCII (simple example)
    add eax, '0'  ; Convert 8 to ASCII '8'
    mov [result_char], al

    ; Write "Sum: "
    mov eax, 4    ; sys_write
    mov ebx, 1    ; stdout
    mov ecx, msg
    mov edx, 5    ; length of "Sum: "
    int 0x80

    ; Write the result character
    mov eax, 4    ; sys_write
    mov ebx, 1    ; stdout
    mov ecx, result_char
    mov edx, 1    ; length of '8'
    int 0x80

    ; Write newline
    mov eax, 4
    mov ebx, 1
    mov ecx, newline
    mov edx, 1
    int 0x80

    ; Exit program
    mov eax, 1    ; sys_exit
    xor ebx, ebx  ; exit code 0
    int 0x80

section .bss
    result_char resb 1
    newline resb 1

Passing Arguments via the Stack

When there are many arguments, or if registers are already in use, the stack is used to pass arguments.

  • Arguments are PUSHed onto the stack before the CALL instruction.
  • The called procedure accesses these arguments relative to the EBP (base pointer) or ESP (stack pointer).

The order of pushing matters! Often, arguments are pushed in reverse order (last argument first).

Accessing Stack Arguments

After CALL, the return address is on the stack. If arguments were pushed, they are below the return address.

Inside the procedure, EBP is typically saved and then set to ESP to create a stable base for accessing arguments and local variables.

  • [EBP+8]: First argument (after saved EBP and return address)
  • [EBP+12]: Second argument
  • And so on...

Code: Stack Arguments (32-bit)

This example shows _multiply_two taking two arguments from the stack and returning their product in EAX.

section .data
    msg db "Product: ", 0

section .text
    global _start

_multiply_two:
    push ebp          ; Save old EBP
    mov ebp, esp      ; Set new EBP to current ESP

    ; Arguments are at [ebp+8] and [ebp+12]
    mov eax, [ebp+8]  ; Get first argument
    imul dword [ebp+12] ; Multiply by second argument

    mov esp, ebp      ; Restore ESP (deallocate local vars if any)
    pop ebp           ; Restore old EBP
    ret 8             ; Return, and pop 8 bytes (2 args * 4 bytes) from stack

_start:
    ; Push arguments in reverse order
    push dword 4      ; Second argument
    push dword 6      ; First argument
    call _multiply_two ; Call the procedure

    ; EAX now holds the product (24)
    ; --- Print result (for demonstration) ---
    ; Convert EAX to ASCII (simple example)
    add eax, '0'  ; Convert 24 to ASCII (this won't work for 24, but for single digit results it does)
    mov [result_char], al

    ; (Code to print 'Product: ' and result_char, and newline omitted for brevity, similar to previous example)
    ; In a real scenario, you'd convert multi-digit numbers properly.

    ; Exit program
    mov eax, 1    ; sys_exit
    xor ebx, ebx  ; exit code 0
    int 0x80

section .bss
    result_char resb 1
    newline resb 1

Returning Values (Registers)

Just like arguments, return values are most commonly passed back in registers for simplicity and speed.

  • For 32-bit x86, the EAX register is typically used for integer return values.
  • For 64-bit x86, RAX is used.
  • Floating-point values might use ST(0) (x87 FPU) or XMM0 (SSE).

If a procedure has no explicit return value, EAX/RAX might still contain leftover data, so don't rely on it.

Returning Values (Stack/Memory)

What if you need to return a large structure or an array?

  • Memory Pointer: The caller might pass a pointer to a memory location where the procedure should store its result.
  • Stack: Less common for simple types, but complex structures could theoretically be built on the stack by the called procedure and then accessed by the caller.

For most basic cases, stick to registers for return values.

Check Your Knowledge

Consider a 32-bit x86 assembly procedure designed to take two integer arguments and return their sum. If the arguments are pushed onto the stack, and the return value is placed in EAX, what is the correct instruction to return from the procedure and clean up the stack?

Recap: Arguments & Returns

In this lesson, we explored how procedures communicate by passing data:

  • Arguments are inputs, passed via registers (for few) or the stack (for many).
  • Return values are outputs, typically placed in a designated register (like EAX/RAX).
  • Calling conventions provide rules for this data exchange.

Mastering these concepts is key to writing robust assembly programs!

無料で開始

AI チューターと学ぶ Assembly — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
12
レッスン
48

よくある質問

「引数と戻り値の受け渡し」レッスンは無料ですか?

はい。「引数と戻り値の受け渡し」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Assembly Language & x86 Low-Level Systems Programmingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Assembly Language & x86 Low-Level Systems Programmingコースには全4レッスンが含まれています。

「引数と戻り値の受け渡し」で何を学びますか?

レジスターとスタックを利用し、プロシージャに引数を渡して値を返すための一般的な規約を学びます。 ブラウザで直接実行するハンズオンコードでAssembly Language & x86 Low-Level Systems Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Assembly Language & x86 Low-Level Systems Programmingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAssembly Language & x86 Low-Level Systems Programmingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「引数と戻り値の受け渡し」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAssembly Language & x86 Low-Level Systems Programmingレッスンでコードを書いて実行できますか?

はい。すべてのAssembly Language & x86 Low-Level Systems Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. コールスタックの基礎
  2. プロシージャの定義と呼び出し
  3. 引数と戻り値の受け渡し
  4. スタックフレームとローカル変数
← Assembly Language & x86 Low-Level Systems Programmingに戻る