使用NASM x86汇编调用int 21h/int 80h触发Segmentation Fault求助
Hey there, let's break down why you're hitting that segmentation fault and fix your code first, then share some solid NASM learning tips.
Why You're Getting a Segmentation Fault
There are a few key issues in your code and setup causing the crash:
- Incorrect string definition
You useddw 'Hello World!', 10to define your message.dw(define word) stores each character as a 2-byte value, but thewritesystem call expects a byte array. You should usedb(define byte) instead. - Missing critical system call parameter
The Linux 32-bitwritesyscall (number 4) requires you to specify the message length in theedxregister. You didn't set this, so the kernel tries to read a random number of bytes from memory—almost always leading to invalid memory access and a segfault. - Architecture/environment mismatch
int 80his the 32-bit Linux system call interface. If you're running a 64-bit OS without compiling for 32-bit mode, or if you're on macOS (which doesn't useint 80hat all), this instruction will fail. Also,_mainis typically a C entry point—Linux assembly uses_startas the standard entry point unless linking with C libraries.
Fixed Code Examples
Here are working versions for common environments:
32-bit Linux
Compile with nasm -f elf32 yourfile.asm && ld -m elf_i386 yourfile.o -o yourfile:
section .data msg: db 'Hello World!', 10 ; Define string as byte array msg_len equ $ - msg ; Auto-calculate message length section .text global _start _start: mov eax, 4 ; Syscall number for sys_write mov ebx, 1 ; File descriptor for stdout mov ecx, msg mov edx, msg_len ; Set message length int 0x80 mov eax, 1 ; Syscall number for sys_exit mov ebx, 0 ; Exit code 0 (success) int 0x80
64-bit Linux
64-bit Linux uses syscall instead of int 80h, with different syscall numbers and register usage. Compile with nasm -f elf64 yourfile.asm && ld yourfile.o -o yourfile:
section .data msg: db 'Hello World!', 10 msg_len equ $ - msg section .text global _start _start: mov rax, 1 ; 64-bit syscall number for sys_write mov rdi, 1 ; File descriptor for stdout mov rsi, msg mov rdx, msg_len syscall mov rax, 60 ; 64-bit syscall number for sys_exit mov rdi, 0 syscall
NASM Learning Resources & Tips
Here's how to level up your NASM skills effectively:
- NASM Official Manual: This is the ultimate reference for syntax, pseudo-instructions, directives, and edge cases. It’s comprehensive and covers everything from basics to advanced usage.
- Syscall Cheat Sheets: Keep a handy reference of Linux syscall numbers and parameter registers for both 32-bit and 64-bit architectures—getting these right is half the battle.
- Debug with GDB: Use the GNU Debugger to step through your code. Inspect registers with
info registers, memory withx/16x msg, and see exactly where your code deviates from expected behavior. - Start Tiny: Build small programs first (printing text, simple arithmetic, reading input) before moving to complex tasks like file I/O or system API interactions.
- Dissect Examples: Look for well-written modern NASM examples, take them apart, and modify them to understand how each component works.
- Join Communities: Participate in low-level programming forums focused on x86 assembly. Ask questions when stuck, and help others if you can—teaching reinforces your own knowledge.
内容的提问来源于stack exchange,提问作者Alex Dukhan
相关产品推荐
相关产品推荐

