這是我的 NASM 組合語言練習筆記。我是根據{YouTube}Intro to x86 Assembly Language進行學習。筆記下多數程式碼是該影片的範例修改而來。 原始程式碼倉庫:https://github.com/code-tutorials/assembly-intro
建置以前你需要先將本範例中的程式碼 tangle
出去。
(sort (org-babel-tangle) 'string<)
接著建置:
make
所有目的執行程式都會在 build
目錄下。你可以參考本筆記內容執行程式,或是在 Emacs org-mode 下執行本筆記。
make clean
- Interrupt Jump Table
- OS Dev.org Wiki
- Linux Syscall Reference
- Linux and Unix exit code tutorial with examples
- Linux系統呼叫(System call)函式增加篇『總整理』
- Linux System Call Table for x86 64
系統呼叫表原始碼位置: /usr/src/linux-headers-4.4.0-98-generic/arch/x86/include/generated/uapi/asm/unistd_64.h
程式碼:
section .text
global _start ;must be declared for linker (ld)
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx, msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
編譯:
nasm -f elf64 hello.asm -o hello.o
ld -m elf_x86_64 hello.o -o hello
執行:
./hello
global _start
_start:
mov eax, 1
mov ebx, 42
sub ebx, 29
int 0x80 ;eax:1 -> terminal print; ebx:status
nasm -f elf64 ex1.asm -o ex1.o
ld -m elf_x86_64 ex1.o -o ex1
./ex1
echo $?
global _start
section .data
msg db "Hello, World!", 0x0a
len equ $ - msg
section .text
_start:
mov eax, 4 ; sys_write system call
mov ebx, 1 ; stdout file descriptor
mov ecx, msg ; byte to write
mov edx, len ; number of bytes to write
int 0x80 ; perform system call
;; exit program
mov eax, 1
mov ebx, 0
int 0x80
nasm -f elf64 ex2.asm -o ex2.o
ld -m elf_x86_64 ex2.o -o ex2
./ex2
;;; about jump
;;; je A,B ; jump if Equal
;;; jne A, B; jump if Not Equal
;;; jg A, B ; jump if Greater
;;; jge A, B; jump if Grater or Equal
;;; jl A, B ; jump if Less
;;; jle A, B ; jump if Less or Equal
global _start
section .text
_start:
mov ecx, 101 ; set exc to 99
mov ebx, 42 ; exit status is 42
mov eax, 1 ; sys_exit system call
cmp ecx, 100 ; compare ecx to 100
jl skip ; jump if less then
mov ebx, 13 ; exit status is 13
skip:
int 0x80
nasm -f elf64 ex3.asm -o ex3.o
ld -m elf_x86_64 ex3.o -o ex3
./ex3
echo $?
global _start
section .text
_start:
mov ebx, 1 ;start ebx at 1
mov ecx, 6 ; number of iterations
label:
add ebx, ebx ; ebx += ebx
dec ecx ; ecx -= 1 ; inc => +1
cmp ecx, 0 ; compare ecx with 0
jg label ; jump to label if greater
mov eax, 1 ; sys_exit system call
int 0x80
nasm -f elf64 ex4.asm -o ex4.o
ld -m elf_x86_64 ex4.o -o ex4
./ex4
echo $?
global _start
section .data
addr db "yellow"
section .text
_start:
mov [addr], byte 'H'
mov [addr+5], byte '!'
mov eax, 4 ; sys_write system call
mov ebx, 1 ; stdout file descriptor
mov ecx, addr ; bytes to write
mov edx, 6 ; number of bytes to write
int 0x80 ; perform system call
mov eax, 1 ; sys_exit system call
mov ebx, 0 ; exit status is 0
int 0x80
nasm -f elf32 ex5.asm -o ex5.o
ld -m elf_i386 ex5.o -o ex5
./ex5
global _start
_start:
sub esp, 4
mov [esp], byte 'H'
mov [esp+1], byte 'e'
mov [esp+2], byte 'y'
mov [esp+3], byte '!'
mov eax, 4 ; sys_write system call
mov ebx, 1 ; stdout file descriptor
mov ecx, esp ; bytes to write
mov edx, 4 ; number of bytes to write
int 0x80 ; perform system call
mov eax, 1 ; sys_exit system call
mov ebx, 0 ; exit status is 0
int 0x80
nasm -f elf32 ex6.asm -o ex6.o
ld -m elf_i386 ex6.o -o ex6
./ex6
global _start
_start:
call func
mov eax, 1 ;(ref:ex7-1 32bit register)
int 0x80
func:
mov ebx, 42
pop eax ;(ref:ex7-1 pop eax)
jmp eax ;(ref:ex7-1 jmp eax)
32 bit 的暫存器用 eax 命名,64 bits 的叫 rax(第(ex7-1 32bit register)行)。
第(ex7-1 pop eax)-(ex7-1 jmp eax)行 同樣可以表示為 ret
,見下方 ex7-2
nasm -f elf32 ex7-1.asm -o ex7-1.o
ld -m elf_i386 ex7-1.o -o ex7-1
./ex7-1
echo $?
global _start
_start:
call func
mov eax, 1
int 0x80
func:
mov ebx, 42
ret
nasm -f elf32 ex7-2.asm -o ex7-2.o
ld -m elf_i386 ex7-2.o -o ex7-2
./ex7-2
echo $?
global _start
_start:
call func
mov eax, 1
mov ebx, 0
int 0x80
func:
push ebp
mov ebp, esp
sub esp, 2
mov [esp], byte 'H'
mov [esp+1], byte 'i'
mov eax, 4 ; sys_write system call
mov ebx, 1 ; stdout file descriptor
mov ecx, esp ; bytes to write
mov edx, 2 ; number of bytes to write
int 0x80 ; perform system call
mov esp, ebp
pop ebp
ret
nasm -f elf32 ex8.asm -o ex8.o
ld -m elf_i386 ex8.o -o ex8
./ex8
- State “DONE” from “NEXT” [2019-09-26 四 16:55]
global _start
_start:
push 21
call times2
mov ebx, eax
mov eax, 1
int 0x80
times2:
push ebp
mov ebp, esp
mov eax, [ebp+8]
add eax, eax
mov esp, ebp
pop ebp
ret
nasm -f elf32 ex9.asm -o ex9.o
ld -m elf_i386 ex9.o -o ex9
./ex9
echo $?
global main
extern printf
section .data
msg db "Testing %i...", 0x0a, 0x00
main:
push ebp
mov ebp, esp
push 123
push msg
call printf
mov eax, 0
mov esp, ebp
pop ebp
ret
nasm -f elf32 ex10.asm -o ex10.o
gcc -m32 ex10.o -o ex10
Note: 貌似我沒安裝 32 位元的 gcc,找不到-lgcc
./ex10
global add42
add42:
push ebp
mov ebp, esp
mov eax, [ebp+8]
add eax, 42
mov esp, ebp
pop ebp
ret
// Function that returns x + 42
int add42(int x);
#include <stdio.h>
#include "add42.h"
int main() {
int result;
result = add42(30);
printf("Result: %i\n", result);
return 0;
}
nasm -f elf32 add42.asm -o add42.o
gcc -m32 add42.o ex11.c -o ex11
./ex11
section .text
global hello_asm ;must be declared for linker (ld)
hello_asm: ;tell linker entry point
mov edx,len ;message length
mov ecx, msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
section .data
msg db 'Hello, NASM!',0xa ;our dear string
len equ $ - msg ;length of our dear string
like Hello World, but not exit process.
extern void hello_asm(void);
#include<stdio.h>
#include<stdlib.h>
void hello_c(){
printf("Hello, C\n");
}
void hello_c();
#include<stdio.h>
#include<stdlib.h>
#include "hello_asm.h"
#include "hello_c.h"
//extern void hello_asm(void);
//extern void hello_c();
int main(void){
printf("Hello, World\n");
hello_asm();
printf("\n");
hello_c();
return 0;
}
nasm -felf64 hello_asm.asm -o hello_asm.o
gcc -c hello_c.c -o hello_c.o
gcc -no-pie hello_main.c hello_c.o hello_asm.o -o hello
./hello
Hello, NASM! Hello, World Hello, C
本筆記除了程式碼部份外,其餘部份採用 CC-3.0 授權。
雖然我以前就有 NASM 的基礎,不過以前看的書的範例平台是使用 Windows,也未太過深入了解系統中斷、系統呼叫。這次有比較深入的學習。
他犧牲自己的一生,揭發政府監控人民的真相! | 永久檔案 | 啾讀。第51集 | 啾啾鞋
理解一件科技設備,並且當它壞掉的時候以正確的方式檢查,嘗試修復它,是一個人對於科技的最基本的責任,不要隨便敷衍科技。
現在的人東西壞掉就換新的,導致沒人在乎一件設備的運作原理,久了以後就造成人們被科技產品反噬。