You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

咨询x86平台下直接与间接call指令的内存布局

Hey there! Comparing direct vs indirect call instructions on x86 is a fantastic way to dig into how x86 handles control flow at the machine code level. Let's break down their memory layouts and behavior step by step:

Direct call (Relative Call)

The direct call instruction uses a relative offset to calculate the target address. Here's its memory layout in 32-bit x86:

  • 1-byte opcode: 0xE8
  • 4-byte signed relative offset: This value is added to the address of the next instruction (right after the call opcode + offset) to get the target function's address.

Example

Suppose we have this assembly:

call my_function
; Next instruction here: 0x08048400

If my_function is at 0x080483F0, the relative offset would be 0x080483F0 - 0x08048400 = -0x10 (which is 0xFFFFFFF0 in two's complement for 32 bits). The memory layout of the call instruction would be:

Address:  0x080483FC  0x080483FD  0x080483FE  0x080483FF  0x08048400
Bytes:     0xE8        0xF0        0xFF        0xFF        0xFF

The CPU computes the target by taking 0x08048400 (next instruction address) + 0xFFFFFFF0 (signed offset) = 0x080483F0, which is the address of my_function.

Indirect call (Absolute/Register/Memory Call)

Indirect call instructions don't use a relative offset—instead, they fetch the target address from a register or a memory location. There are a few common variants in 32-bit x86:

1. Register Indirect call

This uses a general-purpose register to hold the target address. The layout is:

  • 2-byte opcode sequence: 0xFF followed by a ModR/M byte that specifies the target register.

Example

Assembly:

call eax

The machine code is 0xFF 0xD0 (the ModR/M byte 0xD0 encodes "call eax"). The memory layout is just two bytes:

Address:  0x08048400  0x08048401
Bytes:     0xFF        0xD0

The CPU jumps directly to the address stored in eax.

2. Memory Indirect call

This fetches the target address from a specified memory location. The layout is:

  • 2-byte opcode sequence: 0xFF followed by a ModR/M byte that specifies the memory operand.
  • 4-byte memory address (if using a direct absolute memory operand, not a register-based addressing mode).

Example

Assembly:

call [0x08049000]

The machine code is 0xFF 0x15 0x00 0x90 0x04 0x08 (the ModR/M byte 0x15 encodes "call [absolute address]"). The memory layout is six bytes:

Address:  0x08048400  0x08048401  0x08048402  0x08048403  0x08048404  0x08048405
Bytes:     0xFF        0x15        0x00        0x90        0x04        0x08

The CPU reads the 4-byte address stored at 0x08049000 and jumps to that location.

Key Differences in Layout & Behavior

  • Direct call: Compact (5 bytes in 32-bit), uses relative offset, which makes it position-independent (ideal for shared libraries or PIC code). The target is fixed at assembly time unless you patch the offset.
  • Indirect call: Variable length (2 bytes for register targets, 6+ bytes for direct memory targets), uses an absolute address sourced from a register or memory. This enables dynamic target selection—perfect for function pointers, virtual method calls, or any scenario where the target address isn't known until runtime.

内容的提问来源于stack exchange,提问作者JiaHao Xu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:30:24