.file "example1.c"
.section .rodata
.LC0:
.string "Hello world"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4"
.section .note.GNU-stack,"",@progbits
.LC0:
.string "Hello world"
pushq %rbp ; SFP에 rbp 저장
movq %rsp, %rbp ; rbp = rsp
movl $.LC0, %edi ; printf 첫 번째 인자로 LC0에 저장된 스트링 저장
movl $0, %eax ; eax에 0 저장
call printf ; printf 함수 호출
movl $0, %eax ; eax에 0 저장 -> return 값 0으로
popq %rbp ; rbp
ret ; return address 주소로 리턴
위의 분석으로 다음과 같은 소스코드를 작성했다.
#include <stdio.h>
int main(){
printf("Hello world");
return 0;
}
위의 코드를 우분투에서 gcc -o example1 example1.c
로 컴파일 한 후,objdump -d example1
으로 어셈블리 코드를 확인했다.
.file "example2.c"
.section .rodata
.LC0:
.string "result : %d \n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $10, -12(%rbp)
movl $20, -8(%rbp)
movl -8(%rbp), %eax
movl -12(%rbp), %edx
addl %edx, %eax
movl %eax, -4(%rbp)
movl -8(%rbp), %eax
movl -12(%rbp), %edx
addl %edx, %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4"
.section .note.GNU-stack,"",@progbits
.LC0:
.string "result : %d \n"
pushq %rbp ; 함수 프롤로그
movq %rsp, %rbp
subq $16, %rsp ; rsp - 0x10으로 스택 공간 확보
movl $10, -12(%rbp) ; rbp-0xc에 10 저장 (지역변수)
movl $20, -8(%rbp) ; rbp-0x8에 20 저장 (지역변수)
movl -8(%rbp), %eax ; eax에 rbp-0x8 값 저장
movl -12(%rbp), %edx ; edx에 rbp-0xc 값 저장
addl %edx, %eax ; eax = eax + edx
movl %eax, -4(%rbp) ; rbp-0x4에 eax 값 저장 (지역변수)
movl -8(%rbp), %eax ; eax에 rbp-0x8 값 저장
movl -12(%rbp), %edx ; edx에 rbp-0xc 값 저장
addl %edx, %eax ; eax = eax + edx
movl %eax, %esi ; printf의 두 번째 인자 값 eax를 esi에 저장
movl $.LC0, %edi ; printf의 첫 번째 인자 값을 LC0 주소의 스트링으로 가져와서 edi에 저장
movl $0, %eax ; eax를 0으로 초기화
call printf ; printf 함수 호출
movl $0, %eax ; eax(리턴값)에 0 저장
leave ; 함수 에필로그
ret
#include <stdio.h>
int main(){
int a = 10; // rbp-0xc
int b = 20; // rbp-0x8
int c = a + b; // eax = eax + edx, rbp-0x4
printf("result : %d\n", a + b);
return 0;
}
.file "example3.c"
.section .rodata
.LC0:
.string "a is 10"
.LC1:
.string "b is 10"
.LC2:
.string "b is 20"
.LC3:
.string "a=b"
.LC4:
.string "a!=b"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $10, -8(%rbp)
movl $20, -4(%rbp)
cmpl $10, -8(%rbp)
jne .L2
movl $.LC0, %edi
call puts
.L2:
cmpl $10, -4(%rbp)
jne .L3
movl $.LC1, %edi
call puts
jmp .L4
.L3:
cmpl $20, -4(%rbp)
jne .L4
movl $.LC2, %edi
call puts
.L4:
movl -8(%rbp), %eax
cmpl -4(%rbp), %eax
jne .L5
movl $.LC3, %edi
call puts
jmp .L6
.L5:
movl $.LC4, %edi
call puts
.L6:
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4"
.section .note.GNU-stack,"",@progbits
.LC0:
.string "a is 10"
.LC1:
.string "b is 10"
.LC2:
.string "b is 20"
.LC3:
.string "a=b"
.LC4:
.string "a!=b"
main:
pushq %rbp ; 함수 프롤로그
movq %rsp, %rbp
subq $16, %rsp ; rsp - 0x10으로 스택 공간 확보
movl $10, -8(%rbp) ; 스택에 지역변수 값으로 10 저장
movl $20, -4(%rbp) ; 스택에 지역변수 20 저장
cmpl $10, -8(%rbp) ; a == 10 ?
jne .L2 ; 아니면 L2로 점프
movl $.LC0, %edi ; "a is 10" 인자로 가져온다.
call puts ; puts 함수 호출
.L2:
cmpl $10, -4(%rbp) ; b == 10 ?
jne .L3 ; 아니면 L3로 점프
movl $.LC1, %edi ; "b is 10" 스트링 인자로 가져옴
call puts ; puts 함수 호출
jmp .L4 ; L4로 점프
.L3:
cmpl $20, -4(%rbp) ; b == 20 ?
jne .L4 ; 아니면 L4로 점프
movl $.LC2, %edi ; 맞으면 "b is 20" 스트링 puts 인자로 가져옴
call puts ; puts 함수 호출
.L4:
movl -8(%rbp), %eax ; c = a
cmpl -4(%rbp), %eax ; c == b ?
jne .L5 ; 아니면 L5로 점프
movl $.LC3, %edi ; 맞으면 "a=b" 스트링 인자로 가져옴
call puts ; puts 함수 호출
jmp .L6 ; L6로 점프
.L5:
movl $.LC4, %edi ; "a!=b" 스트링 인자로 가져옴
call puts ; puts 함수 호출
.L6:
movl $0, %eax ; 리턴 값 0 저장
leave ; 함수 에필로그
ret
#include <stdio.h>
int main(){
int a = 10;
int b = 20;
int c;
if(a == 10)
puts("a is 10");
if(b == 10)
puts("b is 10");
else if(b == 20)
puts("b is 20");
if(a == b)
puts("a=b");
else
puts("a!=b");
return 0;
}
.file "example4.c"
.section .rodata
.LC0:
.string "result : %d\n"
.text
.globl function
.type function, @function
function:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl -4(%rbp), %eax
imull -8(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size function, .-function
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $50, -8(%rbp)
movl $60, -4(%rbp)
movl -4(%rbp), %edx
movl -8(%rbp), %eax
movl %edx, %esi
movl %eax, %edi
call function
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4"
.section .note.GNU-stack,"",@progbits
subq $16, %rsp ; rsp - 0x10으로 스택 공간 확보
movl %edi, -4(%rbp) ; 매개변수로 가져온 edi를 rbp-4에 넣는다.
movl %esi, -8(%rbp) 두 번째 매개변수로 가져온 값(esi에 있는)을 rbp-8에 저장
movl -4(%rbp), %eax ; eax에 rbp-4 값 저장
imull -8(%rbp), %eax ; eax 와 rbp-8 값 곱해서 eax에 저장
movl %eax, %esi ; 두 번째 인자로 eax를 esi 레지스터에 넣음
movl $.LC0, %edi ; 첫 번째 인자로 "result : %d\n" 가져옴
movl $0, %eax
call printf ; printf 함수 호출
leave
ret
pushq %rbp ; rbp 레지스터를 SFP(Stack Frame Pointer)에 저장
movq %rsp, %rbp ; rbp = rsp
subq $16, %rsp ; rsp - 0x10으로 스택 공간 확보
movl $50, -8(%rbp) ; rbp-8에 50 저장
movl $60, -4(%rbp) ; rbp-4에 60 저장
movl -4(%rbp), %edx ; edx에 rbp-4 값 저장 edx = rbp-4
movl -8(%rbp), %eax ; eax에 rbp-8 값 저장
movl %edx, %esi ; esi 레지스터에 edx 저장 (function의 두 번째 인자)
movl %eax, %edi ; edi 레지스터에 eax 값 저장 (function의 첫 번째 인자)
call function ; function 함수 호출
movl $0, %eax
leave
ret
#include <stdio.h>
int function(int a, int b){
printf("result : %d\n", a * b);
return 0;
}
int main(){
int a = 50;
int b = 60;
function(a, b);
return 0;
}
.file "example5.c"
.section .rodata
.LC0:
.string "number %d \n"
.LC1:
.string "%d * %d = %d \n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $0, -8(%rbp)
jmp .L2
.L3:
movl -8(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
addl $1, -8(%rbp)
.L2:
cmpl $9, -8(%rbp)
jle .L3
movl $0, -4(%rbp)
jmp .L4
.L5:
movl -8(%rbp), %eax
imull -4(%rbp), %eax
movl %eax, %ecx
movl -4(%rbp), %edx
movl -8(%rbp), %eax
movl %eax, %esi
movl $.LC1, %edi
movl $0, %eax
call printf
addl $1, -4(%rbp)
.L4:
cmpl $4, -4(%rbp)
jle .L5
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4"
.section .note.GNU-stack,"",@progbits
.file "example5.c"
.section .rodata
.LC0:
.string "number %d \n"
.LC1:
.string "%d * %d = %d \n"
.text
.globl main
.type main, @function
main:
.LFB0:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp ; 스택 공간 0x10(16바이트)만큼 확보
movl $0, -8(%rbp) ; rbp-0x8에 0 저장 (지역변수)
jmp .L2 ; .L2로 이동
.L3:
movl -8(%rbp), %eax ; eax 레지스터에 rbp-8 저장
movl %eax, %esi ; esi 레지스터에 eax 값(rbp-8) 저장 (printf의 인자2)
movl $.LC0, %edi ; edi 레지스터에 LC0의 문자열 저장 (printf의 인자1)
movl $0, %eax
call printf ; printf 호출
addl $1, -8(%rbp) ; rbp-8에 1 더한다. (i++) (증감식)
.L2:
cmpl $9, -8(%rbp) ; rbp-8 값과 9 비교 (조건식)
jle .L3 ; 작거나 같으면 L3로 이동 (루프 들어감)
movl $0, -4(%rbp) ; 크면 rbp-4에 0 저장 (int j = 0)
jmp .L4 ; L4로 이동 (루프에서 나옴)
.L5:
movl -8(%rbp), %eax ; eax 레지스터에 rbp-8 저장 (a 값)
imull -4(%rbp), %eax ; eax = eax * [rbp-4] (b에 a 곱함)
movl %eax, %ecx ; ecx에 eax 값 저장 (a*b를 eax 레지스터에 저장
movl -4(%rbp), %edx ; edx에 rbp-4 저장 ; 변수 b 를 edx 레지스터에 저장
movl -8(%rbp), %eax ; eax에 rbp-8 저장 (변수 a를 eax 레지스터에 저장)
movl %eax, %esi ; 두 번째 인자 (변수 a)
movl $.LC1, %edi ; 첫 번째 인자
movl $0, %eax
call printf
addl $1, -4(%rbp) ; rbp-4 1 증가 (증감식)
.L4:
cmpl $4, -4(%rbp) ; rbp-4와 4 비교 (조건식)
jle .L5 ; 4보다 작거나 같으면 루프 안으로 들어감
movl $0, %eax ; return 0
leave
ret
#include <stdio.h>
int main(){
int a = 0;
for(int i=0; i<=9; i++){
a = i;
printf("numebr %d \n", a);
}
for(int j=0; j<=4; j++)
{
int b = j;
printf("%d * %d = %d \n", a, b, a*b);
}
return 0;
}
$ objdump -d example5
CodeEngn Basic RCE L01 (0) | 2021.05.01 |
---|---|
리버싱 입문 2. 어셈블러 (0) | 2021.04.06 |
x86_64 assembly code (0) | 2021.04.04 |
어셈블리 명령어 포맷, 명령어 종류 (Instruction Format, Instructions) (0) | 2021.03.26 |
CPU 레지스터 (CPU Register) (0) | 2021.03.26 |