수업 노트 - 어셈블리어

개인적인 참고 용도입니다

 

 

 - 1 의 보수 : 0 은 1 로 , 1 은 0 으로 변경 ( 00000100 → 11111011)
 - 2 의 보수 : 1 의 보수에서 1 을 더한 값 ( 11111011 → 11111100)

 

스택

 - 함수 호출 시 생성되는 지역 변수와 매개 변수가 저장되는 영역
 - 높은 주소에서 낮은 주소로 신장
 - LIFO 구조 : 가장 처음에 들어간 데이터가 가장 나중에 나옴
힙 
 - 동적으로 메모리 할당 시 사용하는 영역
 - 낮은 주소에서 높은 주소로 신장

 

데이터 타입, 데이터 크기
비트 (bit): 0 또는 1
바이트 (byte): 8 비트
워드 (word): 16 비트
더블 워드 (dword): 32 비트 ( ARM 아키텍처에서는 워드)
쿼드 워드 : 64 비트 ( ARM 아키텍처에서는 더블워드)

 

 

x86

 

레지스터
빠른 연산을 위해 사용되는 레지스터 수행 문맥 , 제어 정보 , 데이터 임시 저장
레지스터는 CPU 에 내장된 저장 공간으로 , CPU 아키텍처마다 다름

x86 아키텍처의 범용 목적 레지스터

 

 

 

 

 

<달고나 문서의 범용 레지스터 설명>

 

 * 플래그 레지스터는 값을 바꾸는 명령어가 정해져 있음

 

 

 

x86 CPU의 기본 구조인 IA-32

"명령어 + 인자" 형태

 

명령어 : opcode (ex mov, push)

인자 : operand

 

push 337

mov eax, 1

 -> eax에 1을 넣으라

 -> 옵코드 mov 오퍼랜드는 eax와 1 (앞이 목적지, 뒤가 출발지)

 

EAX - Accumulator. 산술계산을 하며 리턴값을 전달

EDX - Data. EAX와 역할은 같으나 리턴 값의 용도로 사용되지 않음. 

ECX - Count. 루프돌 때 카운트 역할. 0이 될때까지 감소하며 카운트

EBX - 레지스터가 부족하거나 할 때 알아서 사용

 

ESI (Source Index)

EDI (Destination Index)

 

 

 

 

 

명령어 세트 

 - 데이터 이동, 산수/논리 연산, 제어 흐름

참고자료

x86 Instruction Set Reference

https://kernfunny.org/x86/

 

NASM 프로그램 구조
 지시자 : 코드에서 사용할 섹션 , 외부에서 참조할 함수 이름을 선언
 명령어 : 어셈블리어 명령어 세트
 피연산자 : 메모리 , 레지스터 , 데이터
 섹션 : 하나의 작업을 위한 어셈블리어 코드 모음

 

 

 

PUSH, POP

스택에 값 넣기 가져오기 -> 오퍼랜드는 한개만 있으면 됨

push eax, push 1 등

 

MOV

mov eax, 1 -> eax에 1 넣기

 

LEA
주소를 가져오기

 

ADD

src에서 dest로 값 더하기

SUB

빼기

 

 

INT 

인터럽트 일으키기

 

CALL

함수 호출 -> 오퍼랜드 뒤에 번지가 붙음. 해당 번지를 호출하고 작업이 끝나면 CALL 다음 번지로 돌아온다 왜냐하면 CALL로 호출된 코드 안에서는 반드시 RET를 만나 돌아옴

 

80x86 은 서브프로그램을 빠르고 간편하게 호출하기 위해서 스택을 이용한 2 가지 의 명령을 지원한다. CALL 명령은 서브프로그램으로의 무조건 분기를 한 후, 그 다음에 실행될 명령의 주소를 스택에 푸시(push)한다. RET 명령은 그 주소를 팝(pop) 한 후 그 주소로 점프를 한다. 이 명령을 이용할 때, 스택을 정확하게 관리하여 RET 명령에 의해
정확한 주소 값이 팝 될 수 있도록 해야 한다.

 

INC, DEC

INC는 i++ DEC는 i--

 

AND, OR, XOR

dest와 src를 연산함

XOR은 dest와 src를 동일한 오퍼랜드로 처리 가능. -> XOR EAX, EAX 실행하면 EAX가 0으로 초기화

 

NOP

아무것도 하지 말라

 

CMP, JMP

비교해서 점프하는 명령어

 

RETN 

 

함수의 호출규약

호출자가 변수를 피호출자에게 넘기고 , 피호출자의 작업 결과를 반환하는 방법을 정의한 규약

 

 

항상 call 문의 당므 줄을 살펴서 스택을 정리하는 곳이 있는지 확인해야 함.

 

add esp, 8과 같이 스택을 보정하는 코드가 등장하면 __cdecl

__cdecl -> 함수 밖에서 스택 보정

cdecl(←C declaration)은 C 프로그래밍 언어가 기원인 호출 규약으로서 x86 아키텍처용의 수많은 C 컴파일러가 사용한다. (위키피디아)

 

 

__stdcall

stdcall 호출 규약은 마이크로소프트 Win32 API 및 오픈 왓콤 C++의 표준 호출 규약이다. 파스칼 호출 규약의 변형으로서 피호출자는 스택을 정리하는 일을 하지만 매개변수는 _cdecl 호출 규약에서처럼 오른쪽에서 왼쪽 순으로 스택 위로 푸시된다. 레지스터 EAX, ECX, EDX는 함수 내에 사용되도록 규정된다. 반환값은 EAX 레지스터에 저장된다. (위키피디아)

 

__fastcall

파라미터가 2개 이하일 경우 인자를 push로 넣지 않고 ecx와 edx 레지스터를 이용

함수 호출 전에 edx와 ecx에 값을 넣는 것이 보이면 __fastcall 규약 함수

 

__thiscall

 주로 C++에서 이용. 현재 객체의 포인터를 ecx에 전달

ecx+x

ecx+y

ecx+z

 

 

* 보통 함수의 초반부에 레지스터를 push 문으로 스택에 넣는 코드가 등장한다면 앞으로 이 레지스터를 이 함수에서 계속 연산 목적으로 사용하려고 기존 값을 보관해두는 것

 

 

예제

 

hello_world.asm

extern printf
global main
section .data
        message db "hello, world!", 10, 0

section .text
main:
        push    dword message
        call    printf

        mov     eax, 1
        mov     ebx, 0
        int     80h

nasm -felf32 hello_world.asm && ld -I/lib/ld-linux.so.2 -lc --entry main hello_world.o

 

컴파일, 링킹 후 실행 결과

 

 

ld 명령어로 링크

objdump

 

 

 

 

objdump -d > 디스어셈블

 

PUSH  스택에 데이터를 삽입

ESP가 자동으로 4 바이트 감소

 

POP은 스택에서 데이터를 꺼냄

 자동으로 ESP 4바이트 증가

 

 gdb a.out으로 gdb 실행

 disassemble main 혹은 disas main

AT&T에서 인텔 형식으로 변경

set  disassembly-flavor intel

 

 

 

b main

으로 브레이크 포인트 걸기

 

EIP 는 0x08048060을 가리키고 있고 아직 해당 라인을 실행하지 않음

(gdb) disas main 
Dump of assembler code for function main:
=> 0x08048060 <+0>:	push   0x10
   0x08048062 <+2>:	push   0x12345678
   0x08048067 <+7>:	pop    eax
   0x08048068 <+8>:	pop    ebx
End of assembler dump.
(gdb) info reg
eax            0x0	0
ecx            0x0	0
edx            0x0	0
ebx            0x0	0
esp            0xbffff0a0	0xbffff0a0
ebp            0x0	0x0
esi            0x0	0
edi            0x0	0
eip            0x8048060	0x8048060 <main>
eflags         0x202	[ IF ]
cs             0x73	115
ss             0x7b	123
ds             0x7b	123
es             0x7b	123
fs             0x0	0
gs             0x0	0

ESP는 bffff0a0을 가리키고 있음

 

(gdb) info reg $eax
eax            0x0	0
(gdb) info reg $esp
esp            0xbffff0a0	0xbffff0a0

 

한줄만 실행

ni

(gdb) ni
0x08048062 in main ()
(gdb) info reg $esp
esp            0xbffff09c	0xbffff09c
(gdb) disas main
Dump of assembler code for function main:
   0x08048060 <+0>:	push   0x10
=> 0x08048062 <+2>:	push   0x12345678
   0x08048067 <+7>:	pop    eax
   0x08048068 <+8>:	pop    ebx
End of assembler dump.
(gdb) x/x $esp
0xbffff09c:	0x00000010
(gdb)

 

여러개 보기

(gdb) x/4x $esp
0xbffff09c:	0x00000010	0x00000001	0xbffff29d	0x00000000
(gdb) x/10x $esp
0xbffff09c:	0x00000010	0x00000001	0xbffff29d	0x00000000
0xbffff0ac:	0xbffff2b8	0xbffff2c3	0xbffff2d8	0xbffff2ef
0xbffff0bc:	0xbffff301	0xbffff331

 

x/x <- data

x/s <- string

x/x <- instruction

 

(gdb) disas main 
Dump of assembler code for function main:
   0x08048060 <+0>:	push   $0x10
   0x08048062 <+2>:	push   $0x12345678
=> 0x08048067 <+7>:	pop    %eax
   0x08048068 <+8>:	pop    %ebx
End of assembler dump.
(gdb) x/4x $esp
0xbffff098:	0x12345678	0x00000010	0x00000001	0xbffff29d
(gdb) info registers $esp
esp            0xbffff098	0xbffff098

esp가 가리키는 곳에 12345678이 들어가 있음

(gdb) x/4x $esp
0xbffff09c:	0x00000010	0x00000001	0xbffff29d	0x00000000
(gdb) x/x 0xbffff098
0xbffff098:	0x12345678
(gdb) info reg $esp
esp            0xbffff09c	0xbffff09c
(gdb) info reg $eax
eax            0x12345678	305419896

Segmentation Fault in Linux

 

HINT: X86 어셈블리 언어는 가변 길이 명령어
프로그램이 허용되지 않은 메모리 영역에 접근을 시도하거나 , 잘못된 방법으로 메모리 영역에 접근을 시도할 경우 발생
우리 프로그램의 문제는 바로 끝맺음 을 제대로 하지 않은 것
GDB 에서 보면 다음 실행할 명령어 를 제대로 찾지 못하는 것을 확인 가능
프로그램의 끝은 시스템 콜을 이용해야 함

 

 

x/bx 1바이트

x/wx 4바이트 워드

 

(gdb) disas main 
Dump of assembler code for function main:
   0x08048060 <+0>:	push   0x10
   0x08048062 <+2>:	push   0x1234
=> 0x08048067 <+7>:	mov    eax,ebx
   0x08048069 <+9>:	mov    ebx,0xbffff098
   0x0804806e <+14>:	mov    DWORD PTR [ebx],0x10
   0x08048074 <+20>:	mov    ebx,eax
End of assembler dump.
(gdb) x/4x $esp
0xbffff098:	0x00001234	0x00000010	0x00000001	0xbffff29d
(gdb) info reg $ebx
ebx            0x0	0
(gdb) info reg $eax
eax            0x0	0
(gdb) ni
0x08048069 in main ()
(gdb) ni
0x0804806e in main ()
(gdb) disas main 
Dump of assembler code for function main:
   0x08048060 <+0>:	push   0x10
   0x08048062 <+2>:	push   0x1234
   0x08048067 <+7>:	mov    eax,ebx
   0x08048069 <+9>:	mov    ebx,0xbffff098
=> 0x0804806e <+14>:	mov    DWORD PTR [ebx],0x10
   0x08048074 <+20>:	mov    ebx,eax
End of assembler dump.
(gdb)  info rege $ebx
Undefined info command: "rege $ebx".  Try "help info".
(gdb)  info regi $ebx
ebx            0xbffff098	-1073745768
(gdb) x/x 0xbffff098
0xbffff098:	0x00001234
(gdb) ni
0x08048074 in main ()
(gdb) x/x 0xbffff098
0xbffff098:	0x00000010
(gdb) info reg $ebx
ebx            0xbffff098	-1073745768
(gdb) ni
0x08048076 in ?? ()

ebx가 가리키는 곳에다가 10을 집어넣음

 

 

linux system call number

exit number

 

linux system call number

 eax, 1

 ebx, 0

 int 80h

 

 

r/m32 주소 형식 - 대괄호 사용

 

 

 

MOV: 복사
 - 레지스터 → 레지스터
 - 메모리 ↔ 레지스터
 - Immediate 값 → 레지스터 또는 메모리
  - 메모리 ↔ 메모리는 안됨

 

ADD: 더하기 / SUB: 빼기
목적지는 r/m32 또는 레지스터
출발지는 r/m32 또는 레지스터 또는 상수값
출발지와 목적지가 모두 r/m32 일 수는 없음 -> 메모리 to 메모리는 안됨
OF, SF, ZF, AF, PF, CF 에 영향

 

LEA: 복사 (Load Effective Address 유효 주소 로드)
출발지는 r/m32
목적지는 레지스터


레지스터 연산 결과를 레지스터에 저장 (not 포인터)

MOV 와 무엇이 다른가
MOV 는 값을 로드하고 mov eax, [ebp+esp+4]
LEA 는 유효 주소를 로드한다 lea eax, [ebp+esp+4]

 

 

무브에서 대괄호를 쓰는 거는 연산 결과가 가르키는 주소에 있는 값을 넘김

LEA는 연산결과 값 자체를 넣겠다

 

(gdb) disas main 
Dump of assembler code for function main:
   0x08048060 <+0>:	mov    eax,0x1
   0x08048065 <+5>:	mov    ebx,0x4
   0x0804806a <+10>:	mov    ecx,0x7
=> 0x0804806f <+15>:	lea    eax,[eax+ecx*1]
   0x08048072 <+18>:	lea    ebx,[ebx*4+0x0]
   0x08048079 <+25>:	mov    eax,DWORD PTR [eax+ecx*1]
End of assembler dump.
(gdb) ni
0x08048072 in main ()
(gdb) disas main 
Dump of assembler code for function main:
   0x08048060 <+0>:	mov    eax,0x1
   0x08048065 <+5>:	mov    ebx,0x4
   0x0804806a <+10>:	mov    ecx,0x7
   0x0804806f <+15>:	lea    eax,[eax+ecx*1]
=> 0x08048072 <+18>:	lea    ebx,[ebx*4+0x0]
   0x08048079 <+25>:	mov    eax,DWORD PTR [eax+ecx*1]
End of assembler dump.
(gdb) info reg $eax
eax            0x8	8
(gdb) info reg $ebx
ebx            0x4	4
(gdb) info reg $ecx
ecx            0x7	7
(gdb) ni
0x08048079 in main ()
(gdb) info reg $ebx
ebx            0x10	16
(gdb) ni

Program received signal SIGSEGV, Segmentation fault.
0x08048079 in main ()
(gdb) x/x 0x00000008
0x8:	Cannot access memory at address 0x8

 

 


AND: 두 비트가 모두 1 일 때만 1

목적지는 r/m32 또는 레지스터
출발지는 r/m32 또는 레지스터 또는 상수값
OF, CF SF, ZF, PF

OR: 두 비트 중 하나라도 1 이면 1
목적지는 r/m32 또는 레지스터
출발지는 r/m32 또는 레지스터 또는 상수값
OF, CF SF, ZF, PF

XOR: 두 비트가 다를 때만 1
목적지는 r/m32 또는 레지스터
출발지는 r/m32 또는 레지스터 또는 상수값

OF, CF SF, ZF, PF

XOR 은 리버싱에서 유용하게 쓰여요

 

 

 

eax: 0x33 - 00110011

ebx : 0x55 - 01010101

ecx : 0x42 - 01000010

나머지 0xac - 10101100

 

eax and ebx -> 00010001 

-> eax 값이 00010001로 바뀜

 

새 eax or ecx -> 01010011 -> 0x53

-> eax 값이 01010011로 바뀜

 

새새eax xor 0xac -> 11111111 -> 0xFF

 

End of assembler dump.
(gdb) b *main+15
Breakpoint 1 at 0x804806f
(gdb) r
Starting program: /home/x86_exam/exam4/a.out 

Breakpoint 1, 0x0804806f in main ()
(gdb) info reg $eax
eax            0x33	51
(gdb) info reg $ebx
ebx            0x55	85
(gdb) ni
0x08048071 in main ()
(gdb) disas main 
Dump of assembler code for function main:
   0x08048060 <+0>:	mov    eax,0x33
   0x08048065 <+5>:	mov    ebx,0x55
   0x0804806a <+10>:	mov    ecx,0x42
   0x0804806f <+15>:	and    eax,ebx
=> 0x08048071 <+17>:	or     eax,ecx
   0x08048073 <+19>:	xor    eax,0xac
End of assembler dump.
(gdb) info reg $eax
eax            0x11	17
(gdb) ni
0x08048073 in main ()
(gdb) info reg $eax
eax            0x53	83
(gdb) ni
0x08048078 in ?? ()

Program received signal SIGSEGV, Segmentation fault.
0x08048078 in ?? ()
(gdb) info reg $eax
eax            0xff	255

 

 


INC: 피연산자의 값을 1 증가시킴
OF, SF, ZF, AF, PF 에 영향


DEC: 피연산자의 값을 1 감소시킴
OF, SF, ZF, AF, PF 에 영향

 


CMP: 두 값을 비교
cmp 레지스터 , 상수값
cmp r/m32, 상수값
cmp r/m32, 레지스터
cmp 레지스터 , r/m32
출발지에서 목적지 값을 뺀 결과를 플래그에 반영
결과는 버림


TEST: 논리 비교
test eax, eax ( eax 값이 0 인 경우 ZF=1 )
보통 jcc 랑 같이 쓰임

 

 

제어 흐름
조건부 제어 : IF, WHILE, SWITCH
비조건부 제어 : CALL, GOTO, EXCEPTION, INTERRUPT

JMP: Jump!
피연산자 주소로 EIP 를 변경
Short Jump(OF 85): 현재 EIP 값에서 128~127 범위로 이동
Far Jump(75): 다른 세그먼트에 위치한 명령어로 이동


JCC: Jump if Condition Is Met
특정 조건을 만족할 경우 지정한 주소로 제어 흐름을 이동
JNE: Jump Not Equal (ZF=0)
JE: Jump Equal (ZF=1)
JLE: Jump Less Equal (ZF=1 or SF<>OF)

 

CALL: 함수 호출

call printf / 0x80480000 / [eax + 4]
우선 다음 실행할 명령어 주소를 스택에 삽입한 뒤 EIP에 해당 주소를 옮긴 뒤 이동하는 방식외부 함수를 사용하는 경우 반드시 해당 함수가 포함된 라이브러리를 linker 에 함께 전달해야 함

 

 

 

IF Flag

 

(gdb) disas main 
Dump of assembler code for function main:
   0x08048060 <+0>:	mov    eax,0x2
=> 0x08048065 <+5>:	cmp    eax,0x2
   0x08048068 <+8>:	cmp    eax,0x1
   0x0804806b <+11>:	cmp    eax,0x3
   0x0804806e <+14>:	test   eax,eax
   0x08048070 <+16>:	mov    eax,0x0
   0x08048075 <+21>:	test   eax,eax
End of assembler dump.
(gdb) info reg $eflags
eflags         0x202	[ IF ]
(gdb) info reg $eax
eax            0x2	2
(gdb) ni
0x08048068 in main ()
(gdb) info reg $eflags
eflags         0x246	[ PF ZF IF ]

2와 2를 비교해서

PF, ZF 세팅됨

 

PF  연산 결과의 비트 개수에 따라 세팅 -> 여기 짝수

ZF 결과가 0이라 세팅됨

 

 

 

(gdb) 
eflags         0x246	[ PF ZF IF ]
(gdb) ni
0x0804806b in main ()
(gdb) info reg $eflags
eflags         0x202	[ IF ]
(gdb) ni
0x0804806e in main ()
(gdb) info reg $eflags
eflags         0x297	[ CF PF AF SF IF ]
(gdb)

2-1 하면 양수니까 아무것도 세팅이 안됨 IF

2-3 하면 음수가 되니 많이 설정됨 CF PF AF SF IF

 

 -  CF 숫자가 부족하다 - 결과가 음수일 경우 ->앞에 숫자 빌려옴(캐리)

 - AF 하위 비트에서 캐리가 발생할 경우

 - SF 음수

 

 

 

(gdb) info reg $eax
eax            0x2	2
(gdb) info reg $eflags
eflags         0x297	[ CF PF AF SF IF ]
(gdb) ni
0x08048070 in main ()
(gdb) info reg $eflags
eflags         0x202	[ IF ]
(gdb) info reg $eax
eax            0x2	2
(gdb) ni
0x08048075 in main ()
(gdb) info reg $eflags
eflags         0x202	[ IF ]
(gdb) ni
0x08048077 in ?? ()
(gdb) info reg $eflags
eflags         0x246	[ PF ZF IF ]

eax 값이 0이기 때문에 ZF (Zeroflag) 세팅됨

 

 

 

 

 

 

global main

section .text
main:
        mov     ecx, 0
        mov     eax, ecx
        inc     ecx
        cmp     ecx, 255
root@stud:/home/x86_exam/exam6# objdump -d a.out 

a.out:     file format elf32-i386


Disassembly of section .text:

08048060 <main>:
 8048060:	b9 00 00 00 00       	mov    $0x0,%ecx
 8048065:	89 c8                	mov    %ecx,%eax
 8048067:	41                   	inc    %ecx
 8048068:	81 f9 ff 00 00 00    	cmp    $0xff,%ecx
root@stud:/home/x86_exam/exam6# vi exam6.asm
root@stud:/home/x86_exam/exam6# gdb -q a.out 
Reading symbols from a.out...(no debugging symbols found)...done.
(gdb) disas main 
Dump of assembler code for function main:
   0x08048060 <+0>:	mov    $0x0,%ecx
   0x08048065 <+5>:	mov    %ecx,%eax
   0x08048067 <+7>:	inc    %ecx
   0x08048068 <+8>:	cmp    $0xff,%ecx
End of assembler dump.

 

c는 다음 브레이크포인트까지 실행

 

jne 코드 추가

 

(gdb) disas main 
Dump of assembler code for function main:
   0x08048060 <+0>:	mov    ecx,0x0
   0x08048065 <+5>:	mov    eax,ecx
   0x08048067 <+7>:	inc    ecx
   0x08048068 <+8>:	cmp    ecx,0xff
=> 0x0804806e <+14>:	jne    0x8048067 <main+7>
End of assembler dump.
(gdb) info reg $ecx
ecx            0x1	1
(gdb) c
Continuing.

Breakpoint 1, 0x0804806e in main ()
(gdb) info reg $ecx
ecx            0x2	2
(gdb) c
Continuing.

Breakpoint 1, 0x0804806e in main ()
(gdb) info reg $ecx
ecx            0x3	3

 

 

난독화 코드 만들기

 

section .data
        message db "hello world", 10, 0

 

아스키에서 10은 개행문자, 0은 끝이라는 뜻

 

global main
extern printf

section .data
        message db "hello world", 10, 0

section .text
main:
        push    dword message
        mov     eax, [esp]
        mov     ecx, 11
        jmp     loop1

loop1:
        xor     [eax+ecx-1], byte 0x33
        dec     ecx
        jne     loop1
        push    dword message
        call    printf

 

0x64 xor 0x33 -> 0x57

 

root@stud:/home/x86_exam/obfus# ./a.out 
[V__\D\A_W
Segmentation fault (core dumped)
root@stud:/home/x86_exam/obfus# vi obfus.asm
root@stud:/home/x86_exam/obfus# gdb -q a.out 
Reading symbols from a.out...(no debugging symbols found)...done.
(gdb) set disassembly-flavor intel 
(gdb) disas main 
Dump of assembler code for function main:
   0x08048190 <+0>:	push   0x8049264
   0x08048195 <+5>:	mov    eax,DWORD PTR [esp]
   0x08048198 <+8>:	mov    ecx,0xb
   0x0804819d <+13>:	jmp    0x804819f <loop1>
End of assembler dump.
(gdb) disas loop1 
Dump of assembler code for function loop1:
   0x0804819f <+0>:	xor    BYTE PTR [eax+ecx*1-0x1],0x33
   0x080481a4 <+5>:	dec    ecx
   0x080481a5 <+6>:	jne    0x804819f <loop1>
   0x080481a7 <+8>:	push   0x8049264
   0x080481ac <+13>:	call   0x8048180 <printf@plt>
End of assembler dump.
(gdb) x/x 0x8049264
0x8049264:	0x6c6c6568
(gdb) x/s 0x8049264
0x8049264:	"hello world\n"
(gdb) disas main 
Dump of assembler code for function main:
   0x08048190 <+0>:	push   0x8049264
   0x08048195 <+5>:	mov    eax,DWORD PTR [esp]
   0x08048198 <+8>:	mov    ecx,0xb
   0x0804819d <+13>:	jmp    0x804819f <loop1>
End of assembler dump.
(gdb) b *main
Breakpoint 1 at 0x8048190
(gdb) r
Starting program: /home/x86_exam/obfus/a.out 

Breakpoint 1, 0x08048190 in main ()
(gdb) disas m
No symbol "m" in current context.
(gdb) disas main
Dump of assembler code for function main:
=> 0x08048190 <+0>:	push   0x8049264
   0x08048195 <+5>:	mov    eax,DWORD PTR [esp]
   0x08048198 <+8>:	mov    ecx,0xb
   0x0804819d <+13>:	jmp    0x804819f <loop1>
End of assembler dump.
(gdb) ni
0x08048195 in main ()
(gdb) x/4x $esp
0xbffff09c:	0x64	0x92	0x04	0x08
(gdb) x/4wx $esp
0xbffff09c:	0x08049264	0x00000001	0xbffff29d	0x00000000
(gdb) ni
0x08048198 in main ()
(gdb) disas main
Dump of assembler code for function main:
   0x08048190 <+0>:	push   0x8049264
   0x08048195 <+5>:	mov    eax,DWORD PTR [esp]
=> 0x08048198 <+8>:	mov    ecx,0xb
   0x0804819d <+13>:	jmp    0x804819f <loop1>
End of assembler dump.
(gdb) info eg &esp
Undefined info command: "eg &esp".  Try "help info".
(gdb) info reg &esp
Invalid register `&esp'
(gdb) info reg $esp
esp            0xbffff09c	0xbffff09c
(gdb) info reg $eax
eax            0x8049264	134517348
(gdb) ni
0x0804819d in main ()
(gdb) ni
0x0804819f in loop1 ()
(gdb) disas loop1
Dump of assembler code for function loop1:
=> 0x0804819f <+0>:	xor    BYTE PTR [eax+ecx*1-0x1],0x33
   0x080481a4 <+5>:	dec    ecx
   0x080481a5 <+6>:	jne    0x804819f <loop1>
   0x080481a7 <+8>:	push   0x8049264
   0x080481ac <+13>:	call   0x8048180 <printf@plt>
End of assembler dump.
(gdb) info reg $eax
eax            0x8049264	134517348
(gdb) info reg $ecx
ecx            0xb	11
(gdb) x/x 0x8049264+10
0x804926e:	0x00000a64
(gdb) x/s 0x8049264+10
0x804926e:	"d\n"
(gdb) x/s 0x804926e
0x804926e:	"d\n"
(gdb) x/s 0x804926d
0x804926d:	"ld\n"
(gdb) x/s 0x804926c
0x804926c:	"rld\n"
(gdb) x/s 0x804926b
0x804926b:	"orld\n"
(gdb) x/s 0x804926a
0x804926a:	"world\n"
(gdb) x/x 0x804926a
0x804926a:	0x77
(gdb) disas loop1
Dump of assembler code for function loop1:
=> 0x0804819f <+0>:	xor    BYTE PTR [eax+ecx*1-0x1],0x33
   0x080481a4 <+5>:	dec    ecx
   0x080481a5 <+6>:	jne    0x804819f <loop1>
   0x080481a7 <+8>:	push   0x8049264
   0x080481ac <+13>:	call   0x8048180 <printf@plt>
End of assembler dump.
(gdb) ni
0x080481a4 in loop1 ()
(gdb) x/x 0x804926e
0x804926e:	0x57
(gdb) x/s 0x804926e
0x804926e:	"W\n"
(gdb) ni
0x080481a5 in loop1 ()
(gdb) disassemble lopp1
No symbol "lopp1" in current context.
(gdb) disassemble loop1
Dump of assembler code for function loop1:
   0x0804819f <+0>:	xor    BYTE PTR [eax+ecx*1-0x1],0x33
   0x080481a4 <+5>:	dec    ecx
=> 0x080481a5 <+6>:	jne    0x804819f <loop1>
   0x080481a7 <+8>:	push   0x8049264
   0x080481ac <+13>:	call   0x8048180 <printf@plt>
End of assembler dump.
(gdb) info reg $ecx
ecx            0xa	10
(gdb) info reg $eflags
eflags         0x206	[ PF IF ]
(gdb) ni
0x0804819f in loop1 ()
(gdb) disas loop1 
Dump of assembler code for function loop1:
=> 0x0804819f <+0>:	xor    BYTE PTR [eax+ecx*1-0x1],0x33
   0x080481a4 <+5>:	dec    ecx
   0x080481a5 <+6>:	jne    0x804819f <loop1>
   0x080481a7 <+8>:	push   0x8049264
   0x080481ac <+13>:	call   0x8048180 <printf@plt>
End of assembler dump.
(gdb) b *loop1+8
Breakpoint 2 at 0x80481a7
(gdb) c
Continuing.

Breakpoint 2, 0x080481a7 in loop1 ()
(gdb) x/s 0x8049264
0x8049264:	"[V__\\\023D\\A_W\n"
(gdb) disas loop1
Dump of assembler code for function loop1:
   0x0804819f <+0>:	xor    BYTE PTR [eax+ecx*1-0x1],0x33
   0x080481a4 <+5>:	dec    ecx
   0x080481a5 <+6>:	jne    0x804819f <loop1>
=> 0x080481a7 <+8>:	push   0x8049264
   0x080481ac <+13>:	call   0x8048180 <printf@plt>
End of assembler dump.

 

ARM

 

ARM 아키텍처 요약
 - 데이터 타입 : 어셈블리 기본
 - 주소 표기법 : 명령어는 리틀 엔디언 , 데이터는 혼합 사용
 - 레지스터 : 13 개의 범용 레지스터 , 3 개의 특수 레지스터
 - 명령어 세트 : 고정 길이 명령어 형식을 사용
 - 피연산자 : 레지스터 , 메모리 주소 , 주소값 , 숫자
 - 기본 문법 : 모든 작업은 레지스터에서 수행 (Load/Store 구조

 

 =>ARM은 레지스터가 중심이다!

 

 

 

Arm모드, Thumb 모드가 있고 주로 Arm 모드 사용.

 

 

PC는 다음 실행할 명령어


파이프
ARM 명령어를 실행할 때 PC 는 현재 명령어 8 위치한 명령어를 읽는다
Thumb 명령어는 현재 명령어 4 에 위치한 명령어를 읽는다

 

ARM은 명령어 수는 적지만 조건을 붙여서 여러 방식으로 사용 가능

 

 

 

 

 

ARM 실습을 위한 qemu 실행 명령어

 

 

qemu-system-arm -M versatilepb -kernel vmlinuz-3.2.0-4-versatile -initrd initrd.img-3.2.0-4-versatile -hda debian_wheezy_armel_standard.qcow2 -append "root=/dev/sda1" -chardev socket,path=/tmp/port1,server,nowait,id=port1-char -device virtio-serial -device virtserialport,id=port1,chardev=port1-char,name=org.port.0 -net user,hostfwd=tcp::10022-:22 -net nic

 

apt-get 키 오류날 때

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1397BC53640DB551

 

 

ssh root@localhost -p10022

 

 

 

.global main

string:
        .ascii "hello world\n"

main:
        mov     r0, #1
        ldr     r1, =string
        mov     r2, #12
        mov     r7, #4
        swi     0

 

root@debian-armel:~/hello# ls
hello.s
root@debian-armel:~/hello# as hello.s
root@debian-armel:~/hello# as -o hello.o hello.s && ld -entry main hello.o
root@debian-armel:~/hello# ls
a.out  hello.o	hello.s
root@debian-armel:~/hello# ./a.out 
hello world
Segmentation fault
root@debian-armel:~/hello#

 


MOV: 데이터 복사
32 비트 값을 레지스터로 복사

MVN: NOT 데이터 복사
32 비트 값의 NOT 을 레지스터로 복사

 

 

 

코드

.global main

main:
        mov     r5, #5
        mov     r7, $7
        mvn     r7, r5

        mov     r7, $7
        mov     r7, r5, lsl #2
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r5, #5
   0x00008058 <+4>:	mov	r7, #7
   0x0000805c <+8>:	mvn	r7, r5
   0x00008060 <+12>:	mov	r7, #7
   0x00008064 <+16>:	lsl	r7, r5, #2
End of assembler dump.
(gdb) b *main
Breakpoint 1 at 0x8054
(gdb) r
Starting program: /root/hello/exam1/a.out 

Breakpoint 1, 0x00008054 in main ()
(gdb) disas main 
Dump of assembler code for function main:
=> 0x00008054 <+0>:	mov	r5, #5
   0x00008058 <+4>:	mov	r7, #7
   0x0000805c <+8>:	mvn	r7, r5
   0x00008060 <+12>:	mov	r7, #7
   0x00008064 <+16>:	lsl	r7, r5, #2
End of assembler dump.
(gdb) info reg
r0             0x0	0
r1             0x0	0
r2             0x0	0
r3             0x0	0
r4             0x0	0
r5             0x0	0
r6             0x0	0
r7             0x0	0
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x0	0
r12            0x0	0
sp             0xbefffc90	0xbefffc90
lr             0x0	0
pc             0x8054	0x8054 <main>
cpsr           0x10	16

 

(gdb) ni
0x00008058 in main ()
(gdb) ni
0x0000805c in main ()
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r5, #5
   0x00008058 <+4>:	mov	r7, #7
=> 0x0000805c <+8>:	mvn	r7, r5
   0x00008060 <+12>:	mov	r7, #7
   0x00008064 <+16>:	lsl	r7, r5, #2
End of assembler dump.
(gdb) info reg $r5
r5             0x5	5
(gdb) info reg $r7
r7             0x7	7

(gdb) ni
0x00008060 in main ()
(gdb) info reg $r7
r7             0xfffffffa	4294967290

mvn

00000101을 not 하면 11111010 -> 16 진수로 FA

 

mov r7, r5

r5에 5가 들어있는데 그걸 not해서 그 결과를 r7에 넣겠다

 

lsl ->  r5값을 2만큼 쉬프트

00000101 ->쉬프트하면  00010100 -> 이게 r7에 들어감 20임

(gdb) ni
Cannot access memory at address 0x0
0x00008068 in ?? ()
(gdb) info reg $r7
r7             0x14	20

 

 

 

데이터 비교

 


CMN: 더하기 비교
cmn r0, r1 → r0 + r1

CMP: 빼기 비교
cmp r0, r1 → r0 r1

TEQ: 두 값이 같은지 비교 (xor)
teq r0, r1 → r0 ^ r1

TST: 비트 테스트 (and)
tst r0, r1 → r0 & r1

레지스터 비교 결과에 따라 CPSR 플래그 업데이트

 

 

 

.global main

main:
        mov     r0, #0
        mov     r1, #1
        mov     r2, #254,

        cmp     r0, r1
        cmn     r2, r2

        tst     r0, r0
        teq     r0, r1

        cmp     r0, #0
        moveq   r0, #2

 

moveq는 ZF 값에 따라 실행여부 결정

cpsr 기본값 10

 

(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #0
   0x00008058 <+4>:	mov	r1, #1
   0x0000805c <+8>:	mov	r2, #254	; 0xfe
=> 0x00008060 <+12>:	cmp	r0, r1
   0x00008064 <+16>:	cmn	r2, r2
   0x00008068 <+20>:	tst	r0, r0
   0x0000806c <+24>:	teq	r0, r1
   0x00008070 <+28>:	cmp	r0, #0
   0x00008074 <+32>:	moveq	r0, #2
End of assembler dump.
(gdb) info registers 
r0             0x0	0
r1             0x1	1
r2             0xfe	254
r3             0x0	0
r4             0x0	0
r5             0x0	0
r6             0x0	0
r7             0x0	0
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x0	0
r12            0x0	0
sp             0xbefffc90	0xbefffc90
lr             0x0	0
pc             0x8060	0x8060 <main+12>
cpsr           0x10	16
(gdb) info reg $cpsr
cpsr           0x10	16
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #0
   0x00008058 <+4>:	mov	r1, #1
   0x0000805c <+8>:	mov	r2, #254	; 0xfe
=> 0x00008060 <+12>:	cmp	r0, r1
   0x00008064 <+16>:	cmn	r2, r2
   0x00008068 <+20>:	tst	r0, r0
   0x0000806c <+24>:	teq	r0, r1
   0x00008070 <+28>:	cmp	r0, #0
   0x00008074 <+32>:	moveq	r0, #2
End of assembler dump.
(gdb) ni
0x00008064 in main ()
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #0
   0x00008058 <+4>:	mov	r1, #1
   0x0000805c <+8>:	mov	r2, #254	; 0xfe
   0x00008060 <+12>:	cmp	r0, r1
=> 0x00008064 <+16>:	cmn	r2, r2
   0x00008068 <+20>:	tst	r0, r0
   0x0000806c <+24>:	teq	r0, r1
   0x00008070 <+28>:	cmp	r0, #0
   0x00008074 <+32>:	moveq	r0, #2
End of assembler dump.
(gdb) info reg $cpsr
cpsr           0x80000010	-2147483632
(gdb) ni
0x00008068 in main ()
(gdb) info reg $cpsr
cpsr           0x10	16
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #0
   0x00008058 <+4>:	mov	r1, #1
   0x0000805c <+8>:	mov	r2, #254	; 0xfe
   0x00008060 <+12>:	cmp	r0, r1
   0x00008064 <+16>:	cmn	r2, r2
=> 0x00008068 <+20>:	tst	r0, r0
   0x0000806c <+24>:	teq	r0, r1
   0x00008070 <+28>:	cmp	r0, #0
   0x00008074 <+32>:	moveq	r0, #2
End of assembler dump.
(gdb) ni
0x0000806c in main ()
(gdb) info reg $cpsr
cpsr           0x40000010	1073741840
(gdb) ni
0x00008070 in main ()
(gdb) info reg $cpsr
cpsr           0x10	16
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #0
   0x00008058 <+4>:	mov	r1, #1
   0x0000805c <+8>:	mov	r2, #254	; 0xfe
   0x00008060 <+12>:	cmp	r0, r1
   0x00008064 <+16>:	cmn	r2, r2
   0x00008068 <+20>:	tst	r0, r0
   0x0000806c <+24>:	teq	r0, r1
=> 0x00008070 <+28>:	cmp	r0, #0
   0x00008074 <+32>:	moveq	r0, #2
End of assembler dump.
(gdb) ni
0x00008074 in main ()
(gdb) info reg $cpsr
cpsr           0x60000010	1610612752
(gdb) info reg $r0
r0             0x0	0
(gdb) ni
Cannot access memory at address 0x0
0x00008078 in ?? ()
(gdb) info reg $cpsr
cpsr           0x60000010	1610612752
(gdb) info reg $r0
r0             0x2	2

연산 결과에 따라서 플래그 값이 변경

cpsr을 이진수로 긁어서 봐야한다

 

위에 나온 플래그 설명 참조

 

 

 

 

 

 

점프는 돌아 오는 걸 가정하지 않음

Call은 서브루틴을 콜하는거라 돌아오게 되어있음

 

BL은 Call과 비슷하고 B는 Jmp와 비슷

 

 

.global main

main:
        mov     r0, #2
        mov     r1, #0
        b       loop

loop:
        sub     r0, r0, #1
        cmp     r0, r1
        bne     loop

        mov     r7, #1
        swi     0

swi 0이 exit 역할

 

section과 function을 구분해야 할 필요가 있다

위의 main과 loop는 함수 호출 규약을 따르지 않기 때문에 섹션으로 보는 것이 맞음

 

 

(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	mov	r1, #0
   0x0000805c <+8>:	b	0x8060 <loop>
End of assembler dump.
(gdb) disas loop 
Dump of assembler code for function loop:
   0x00008060 <+0>:	sub	r0, r0, #1
   0x00008064 <+4>:	cmp	r0, r1
   0x00008068 <+8>:	bne	0x8060 <loop>
   0x0000806c <+12>:	mov	r7, #1
   0x00008070 <+16>:	svc	0x00000000
End of assembler dump.
(gdb) b *main+8
Breakpoint 1 at 0x805c
(gdb) r
Starting program: /root/hello/exam3/a.out 
Breakpoint 1, 0x0000805c in main ()
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	mov	r1, #0
=> 0x0000805c <+8>:	b	0x8060 <loop>
End of assembler dump.
(gdb) ni
0x00008060 in loop ()
(gdb) disas loop 
Dump of assembler code for function loop:
=> 0x00008060 <+0>:	sub	r0, r0, #1
   0x00008064 <+4>:	cmp	r0, r1
   0x00008068 <+8>:	bne	0x8060 <loop>
   0x0000806c <+12>:	mov	r7, #1
   0x00008070 <+16>:	svc	0x00000000
End of assembler dump.
(gdb) info reg $r0
r0             0x2	2
(gdb) info reg $r1
r1             0x0	0
(gdb) ni
0x00008064 in loop ()
(gdb) info reg $r0
r0             0x1	1
(gdb) info reg $cpsr
cpsr           0x10	16
(gdb) disas loop
Dump of assembler code for function loop:
   0x00008060 <+0>:	sub	r0, r0, #1
=> 0x00008064 <+4>:	cmp	r0, r1
   0x00008068 <+8>:	bne	0x8060 <loop>
   0x0000806c <+12>:	mov	r7, #1
   0x00008070 <+16>:	svc	0x00000000
End of assembler dump.
(gdb) ni
0x00008068 in loop ()
(gdb) info reg $cpsr
cpsr           0x20000010	536870928
(gdb) ^CQuit
(gdb) disas loop 
Dump of assembler code for function loop:
   0x00008060 <+0>:	sub	r0, r0, #1
   0x00008064 <+4>:	cmp	r0, r1
=> 0x00008068 <+8>:	bne	0x8060 <loop>
   0x0000806c <+12>:	mov	r7, #1
   0x00008070 <+16>:	svc	0x00000000
End of assembler dump.
(gdb) ni
0x00008060 in loop ()
(gdb) info reg $cpsr
cpsr           0x20000010	536870928
(gdb) disas loop 
Dump of assembler code for function loop:
=> 0x00008060 <+0>:	sub	r0, r0, #1
   0x00008064 <+4>:	cmp	r0, r1
   0x00008068 <+8>:	bne	0x8060 <loop>
   0x0000806c <+12>:	mov	r7, #1
   0x00008070 <+16>:	svc	0x00000000
End of assembler dump.
(gdb) ni
0x00008064 in loop ()
(gdb) disas loop 
Dump of assembler code for function loop:
   0x00008060 <+0>:	sub	r0, r0, #1
=> 0x00008064 <+4>:	cmp	r0, r1
   0x00008068 <+8>:	bne	0x8060 <loop>
   0x0000806c <+12>:	mov	r7, #1
   0x00008070 <+16>:	svc	0x00000000
End of assembler dump.
(gdb) info reg $cpsr
cpsr           0x20000010	536870928
(gdb) ni
0x00008068 in loop ()
(gdb) info reg $cpsr
cpsr           0x60000010	1610612752
(gdb) ni
0x0000806c in loop ()
(gdb) disas loop
Dump of assembler code for function loop:
   0x00008060 <+0>:	sub	r0, r0, #1
   0x00008064 <+4>:	cmp	r0, r1
   0x00008068 <+8>:	bne	0x8060 <loop>
=> 0x0000806c <+12>:	mov	r7, #1
   0x00008070 <+16>:	svc	0x00000000
End of assembler dump.
(gdb) c
Continuing.
[Inferior 1 (process 8968) exited normally]
(gdb)

 

제로플래그 0될때까지 루프 돈다

 

 

 

 

 

 

 

Load-Store

지금까지는 x86과 유사했으나 이 경우에는 특이함

 

LD -> LoaD

ST -> STore

R은 레지스터

M은 멀티플(레지스터)로 이해

 

 

로드는 목적지가 무조건 레지스터. 출발지는 메모리 영역

 

대괄호 안에 있는 값만 영향을 받는다고 생각하면 됨(Post 인덱스는 R1에 대괄호 생략)

Post 인덱스는 목적지에 R0에 오프셋을 넣어주지 않음

 

ldr은 #대신 =사용해야 함

str은 ldr이랑 반대의 순서로 넣는다고 생각해야함. (앞에서 뒤로 감) r1에 있는 값을 r0에서 8떨어진 위치에 넣겠다

 

 

 

 

(gdb) disas main 
Dump of assembler code for function main:
   0x00008060 <+0>:	mov	r1, #255	; 0xff
   0x00008064 <+4>:	mov	r0, sp
   0x00008068 <+8>:	ldr	r1, [pc, #-0]	; 0x8070 <main+16>
   0x0000806c <+12>:	str	r1, [r0, #8]
   0x00008070 <+16>:	andeq	r8, r0, r4, asr r0
End of assembler dump.
(gdb) q
root@debian-armel:~/exam4# cat exam4.s
.global main

string:
	.ascii "hello world\n"

main:
	ldr	r1, =255
	mov	r0, r13
	ldr	r1, =string
	str	r1, [r0, #8]

main+0번줄

 

ldr 숫자가 특정 범위 안에 있는 값이면 mov로 바꿈 -> 굳이 메모리에서 가져올 필요 없음 -> 코드의 효율성

 

 

(gdb) disas main 
Dump of assembler code for function main:
   0x00008060 <+0>:	mov	r1, #255	; 0xff
   0x00008064 <+4>:	mov	r0, sp
=> 0x00008068 <+8>:	ldr	r1, [pc, #-0]	; 0x8070 <main+16>
   0x0000806c <+12>:	str	r1, [r0, #8]
   0x00008070 <+16>:	andeq	r8, r0, r4, asr r0
End of assembler dump.
(gdb) info reg $pc
pc             0x8068	0x8068 <main+8>
(gdb) x/x 0x00008070
0x8070 <main+16>:	0x00008054
(gdb) x/x 0x00008054
0x8054 <string>:	0x6c6c6568
(gdb) x/s 0x00008054
0x8054 <string>:	 "hello world\n\377\020\240\343\r"
(gdb)

string을 r1으로 옮기라고 했는데 pc 안에 있는 주소가 가리키는 곳의 데이터를 r1로 올기는 것으로 바뀜

arm은 sp가 다다음 명령어 가리킴 +8에서 pc는 8070 (다다음줄)

8070에는 8054라는 값이 있음 -> 임의로 adeq라는 명령으로 읽었지만 사실 값은 string임 (hello world)

 

 

(gdb) disas main 
Dump of assembler code for function main:
   0x00008060 <+0>:	mov	r1, #255	; 0xff
   0x00008064 <+4>:	mov	r0, sp
=> 0x00008068 <+8>:	ldr	r1, [pc, #-0]	; 0x8070 <main+16>
   0x0000806c <+12>:	str	r1, [r0, #8]
   0x00008070 <+16>:	andeq	r8, r0, r4, asr r0
End of assembler dump.
(gdb) ni
0x0000806c in main ()
(gdb) disas main 
Dump of assembler code for function main:
   0x00008060 <+0>:	mov	r1, #255	; 0xff
   0x00008064 <+4>:	mov	r0, sp
   0x00008068 <+8>:	ldr	r1, [pc, #-0]	; 0x8070 <main+16>
=> 0x0000806c <+12>:	str	r1, [r0, #8]
   0x00008070 <+16>:	andeq	r8, r0, r4, asr r0
End of assembler dump.
(gdb) info reg $r1
r1             0x8054	32852
(gdb) info reg $r0
r0             0xbefffcb0	3204447408
(gdb) ni
0x00008070 in main ()
(gdb) x/4x 0xbefffcb0
0xbefffcb0:	0x01	0x00	0x00	0x00
(gdb) x/4wx 0xbefffcb0
0xbefffcb0:	0x00000001	0xbefffdc9	0x00008054	0xbefffddb
(gdb) info reg $cpsr
cpsr           0x10	16

r0 ->0xbefffcb0

r0, #8 > 0xbefffcb8 >-요기에다가 r1-> 8054를 넣겠다

 

=> 0x0000806c <+12>: str r1, [r0, #8]

 

andeq는 비록 8054로 문자열이지만 제로플래그도 없어서 결국 실행되지 않음

 

 

 

느낌표는 연산 하고 나서 앞에 있는 거를 갱신시킨다

 

 

 

 

 

 

 

 

.global main

main:
        mov     r0, #2
        str     r0, [r13, #4]
        add     r0, r0, #1
        str     r0, [r13, #8]
        mov     r0, r13

 

 

 

(gdb) b* main
Breakpoint 1 at 0x8054
(gdb) r
Starting program: /root/exam5/a.out 

Breakpoint 1, 0x00008054 in main ()
(gdb) disas main 
Dump of assembler code for function main:
=> 0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	str	r0, [sp, #4]
   0x0000805c <+8>:	add	r0, r0, #1
   0x00008060 <+12>:	str	r0, [sp, #8]
   0x00008064 <+16>:	mov	r0, sp
End of assembler dump.
(gdb) ni
0x00008058 in main ()
(gdb) info reg $r0
r0             0x2	2
(gdb) ni
0x0000805c in main ()
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	str	r0, [sp, #4]
=> 0x0000805c <+8>:	add	r0, r0, #1
   0x00008060 <+12>:	str	r0, [sp, #8]
   0x00008064 <+16>:	mov	r0, sp
End of assembler dump.
(gdb) info reg $sp
sp             0xbefffcb0	0xbefffcb0
(gdb) x/4x $sp
0xbefffcb0:	0x00000001	0x00000002	0x00000000	0xbefffddb
(gdb) ni
0x00008060 in main ()
(gdb) info reg $r0
r0             0x3	3
(gdb) ni
0x00008064 in main ()
(gdb) disas main
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	str	r0, [sp, #4]
   0x0000805c <+8>:	add	r0, r0, #1
   0x00008060 <+12>:	str	r0, [sp, #8]
=> 0x00008064 <+16>:	mov	r0, sp
End of assembler dump.
(gdb) x/x 0xbefffcb8
0xbefffcb8:	0x00000003
(gdb) x/4x $sp
0xbefffcb0:	0x00000001	0x00000002	0x00000003	0xbefffddb

 

(gdb) x/4x $sp
0xbefffcb0: 0x00000001 0x00000002 0x00000000 0xbefffddb

 

스택에 1은 원래 들어가있던거고 +4지점에 2를 넣은거임

 

수업 제대로 안들음- >필요시 다시 공부 필요...

강의제목 -  ldm, stm 명령어

(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	str	r0, [sp, #4]
   0x0000805c <+8>:	add	r0, r0, #1
   0x00008060 <+12>:	str	r0, [sp, #8]
   0x00008064 <+16>:	mov	r0, sp
   0x00008068 <+20>:	ldm	r0!, {r1, r2, r3}
   0x0000806c <+24>:	mov	r0, sp
   0x00008070 <+28>:	ldmib	r0!, {r1, r2, r3}
   0x00008074 <+32>:	mov	r0, sp
   0x00008078 <+36>:	ldmda	r0!, {r1, r2, r3}
   0x0000807c <+40>:	mov	r0, sp
   0x00008080 <+44>:	ldmda	r0!, {r1, r2, r3}
End of assembler dump.
(gdb) b *main+16
Breakpoint 1 at 0x8064
(gdb) r
Starting program: /root/exam5/a.out 

Breakpoint 1, 0x00008064 in main ()
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	str	r0, [sp, #4]
   0x0000805c <+8>:	add	r0, r0, #1
   0x00008060 <+12>:	str	r0, [sp, #8]
=> 0x00008064 <+16>:	mov	r0, sp
   0x00008068 <+20>:	ldm	r0!, {r1, r2, r3}
   0x0000806c <+24>:	mov	r0, sp
   0x00008070 <+28>:	ldmib	r0!, {r1, r2, r3}
   0x00008074 <+32>:	mov	r0, sp
   0x00008078 <+36>:	ldmda	r0!, {r1, r2, r3}
   0x0000807c <+40>:	mov	r0, sp
   0x00008080 <+44>:	ldmda	r0!, {r1, r2, r3}
End of assembler dump.
(gdb) x/4x 0xbefffcb0
0xbefffcb0:	0x00000001	0x00000002	0x00000003	0xbefffddb
(gdb) info reg $r0
r0             0x3	3
(gdb) ni
0x00008068 in main ()
(gdb) info reg $r0
r0             0xbefffcb0	3204447408
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	str	r0, [sp, #4]
   0x0000805c <+8>:	add	r0, r0, #1
   0x00008060 <+12>:	str	r0, [sp, #8]
   0x00008064 <+16>:	mov	r0, sp
=> 0x00008068 <+20>:	ldm	r0!, {r1, r2, r3}
   0x0000806c <+24>:	mov	r0, sp
   0x00008070 <+28>:	ldmib	r0!, {r1, r2, r3}
   0x00008074 <+32>:	mov	r0, sp
   0x00008078 <+36>:	ldmda	r0!, {r1, r2, r3}
   0x0000807c <+40>:	mov	r0, sp
   0x00008080 <+44>:	ldmda	r0!, {r1, r2, r3}
End of assembler dump.
(gdb) ni
0x0000806c in main ()
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	str	r0, [sp, #4]
   0x0000805c <+8>:	add	r0, r0, #1
   0x00008060 <+12>:	str	r0, [sp, #8]
   0x00008064 <+16>:	mov	r0, sp
   0x00008068 <+20>:	ldm	r0!, {r1, r2, r3}
=> 0x0000806c <+24>:	mov	r0, sp
   0x00008070 <+28>:	ldmib	r0!, {r1, r2, r3}
   0x00008074 <+32>:	mov	r0, sp
   0x00008078 <+36>:	ldmda	r0!, {r1, r2, r3}
   0x0000807c <+40>:	mov	r0, sp
   0x00008080 <+44>:	ldmda	r0!, {r1, r2, r3}
End of assembler dump.
(gdb) info reg
r0             0xbefffcbc	3204447420
r1             0x1	1
r2             0x2	2
r3             0x3	3
r4             0x0	0
r5             0x0	0
r6             0x0	0
r7             0x0	0
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x0	0
r12            0x0	0
sp             0xbefffcb0	0xbefffcb0
lr             0x0	0
pc             0x806c	0x806c <main+24>
cpsr           0x10	16
(gdb) x/x 0xbefffcbc
0xbefffcbc:	0xbefffddb
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	str	r0, [sp, #4]
   0x0000805c <+8>:	add	r0, r0, #1
   0x00008060 <+12>:	str	r0, [sp, #8]
   0x00008064 <+16>:	mov	r0, sp
   0x00008068 <+20>:	ldm	r0!, {r1, r2, r3}
=> 0x0000806c <+24>:	mov	r0, sp
   0x00008070 <+28>:	ldmib	r0!, {r1, r2, r3}
   0x00008074 <+32>:	mov	r0, sp
   0x00008078 <+36>:	ldmda	r0!, {r1, r2, r3}
   0x0000807c <+40>:	mov	r0, sp
   0x00008080 <+44>:	ldmda	r0!, {r1, r2, r3}
End of assembler dump.
(gdb) ni
0x00008070 in main ()
(gdb) info reg $r0
r0             0xbefffcb0	3204447408
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	str	r0, [sp, #4]
   0x0000805c <+8>:	add	r0, r0, #1
   0x00008060 <+12>:	str	r0, [sp, #8]
   0x00008064 <+16>:	mov	r0, sp
   0x00008068 <+20>:	ldm	r0!, {r1, r2, r3}
   0x0000806c <+24>:	mov	r0, sp
=> 0x00008070 <+28>:	ldmib	r0!, {r1, r2, r3}
   0x00008074 <+32>:	mov	r0, sp
   0x00008078 <+36>:	ldmda	r0!, {r1, r2, r3}
   0x0000807c <+40>:	mov	r0, sp
   0x00008080 <+44>:	ldmda	r0!, {r1, r2, r3}
End of assembler dump.
(gdb) ni
0x00008074 in main ()
(gdb) info reg
r0             0xbefffcbc	3204447420
r1             0x2	2
r2             0x3	3
r3             0xbefffddb	3204447707
r4             0x0	0
r5             0x0	0
r6             0x0	0
r7             0x0	0
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x0	0
r12            0x0	0
sp             0xbefffcb0	0xbefffcb0
lr             0x0	0
pc             0x8074	0x8074 <main+32>
cpsr           0x10	16
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	str	r0, [sp, #4]
   0x0000805c <+8>:	add	r0, r0, #1
   0x00008060 <+12>:	str	r0, [sp, #8]
   0x00008064 <+16>:	mov	r0, sp
   0x00008068 <+20>:	ldm	r0!, {r1, r2, r3}
   0x0000806c <+24>:	mov	r0, sp
   0x00008070 <+28>:	ldmib	r0!, {r1, r2, r3}
=> 0x00008074 <+32>:	mov	r0, sp
   0x00008078 <+36>:	ldmda	r0!, {r1, r2, r3}
   0x0000807c <+40>:	mov	r0, sp
   0x00008080 <+44>:	ldmda	r0!, {r1, r2, r3}
End of assembler dump.
(gdb) ni
0x00008078 in main ()
(gdb) info reg
r0             0xbefffcb0	3204447408
r1             0x2	2
r2             0x3	3
r3             0xbefffddb	3204447707
r4             0x0	0
r5             0x0	0
r6             0x0	0
r7             0x0	0
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x0	0
r12            0x0	0
sp             0xbefffcb0	0xbefffcb0
lr             0x0	0
pc             0x8078	0x8078 <main+36>
cpsr           0x10	16
(gdb) x/x 0xbefffca4
0xbefffca4:	0x00000000
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r0, #2
   0x00008058 <+4>:	str	r0, [sp, #4]
   0x0000805c <+8>:	add	r0, r0, #1
   0x00008060 <+12>:	str	r0, [sp, #8]
   0x00008064 <+16>:	mov	r0, sp
   0x00008068 <+20>:	ldm	r0!, {r1, r2, r3}
   0x0000806c <+24>:	mov	r0, sp
   0x00008070 <+28>:	ldmib	r0!, {r1, r2, r3}
   0x00008074 <+32>:	mov	r0, sp
=> 0x00008078 <+36>:	ldmda	r0!, {r1, r2, r3}
   0x0000807c <+40>:	mov	r0, sp
   0x00008080 <+44>:	ldmda	r0!, {r1, r2, r3}
End of assembler dump.
(gdb) ni
0x0000807c in main ()
(gdb) nni
Undefined command: "nni".  Try "help".
(gdb) ni
0x00008080 in main ()
(gdb) info reg
r0             0xbefffcb0	3204447408
r1             0x0	0
r2             0x0	0
r3             0x1	1
r4             0x0	0
r5             0x0	0
r6             0x0	0
r7             0x0	0
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x0	0
r12            0x0	0
sp             0xbefffcb0	0xbefffcb0
lr             0x0	0
pc             0x8080	0x8080 <main+44>
cpsr           0x10	16
(gdb) ni
Cannot access memory at address 0x0
0x00008084 in ?? ()
(gdb) info reg
r0             0xbefffca4	3204447396
r1             0x0	0
r2             0x0	0
r3             0x1	1
r4             0x0	0
r5             0x0	0
r6             0x0	0
r7             0x0	0
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x0	0
r12            0x0	0
sp             0xbefffcb0	0xbefffcb0
lr             0x0	0
pc             0x8084	0x8084
cpsr           0x10	16

 

R11-R9 바이트만큼 R10이 위치한 곳에 메모리를 복사하라(R9가 R11이 될때까지 올라감)

 

 

FD, ED 중요!

 

.global main

main:
        mov     r1, #10
        mov     r2, #20
        mov     r3, #30
        mov     r4, sp
        stmdd   sp!, {r1-r3}
        eor     r1, r1
        eor     r2, r2
        eor     r3, r3
        ldmdb   r4, {r1-r3}

stmdd -> r1~r3값을 스택포인트 가리키는 곳에 집어넣고, 디센딩이니까 스택포인트 낮추고 스택포인트에 갱신

eor -> r1,r2,r3를 모두 0으로 만듬

ldmdb 레지스터로 팝 r4가 가리키는 지점부터 시작해서 메모리 주소를 올리면서 r1~r3 값 넣음

 

 

(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r1, #10
   0x00008058 <+4>:	mov	r2, #20
   0x0000805c <+8>:	mov	r3, #30
   0x00008060 <+12>:	mov	r4, sp
   0x00008064 <+16>:	push	{r1, r2, r3}
   0x00008068 <+20>:	eor	r1, r1, r1
   0x0000806c <+24>:	eor	r2, r2, r2
   0x00008070 <+28>:	eor	r3, r3, r3
   0x00008074 <+32>:	ldmdb	r4, {r1, r2, r3}
End of assembler dump.

stmfd가 push로 바뀜 (어차피 걍 스택포인트에 넣는 거라 푸쉬하는 거랑 같음)

 

(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r1, #10
   0x00008058 <+4>:	mov	r2, #20
   0x0000805c <+8>:	mov	r3, #30
   0x00008060 <+12>:	mov	r4, sp
   0x00008064 <+16>:	push	{r1, r2, r3}
   0x00008068 <+20>:	eor	r1, r1, r1
   0x0000806c <+24>:	eor	r2, r2, r2
   0x00008070 <+28>:	eor	r3, r3, r3
   0x00008074 <+32>:	ldmdb	r4, {r1, r2, r3}
End of assembler dump.
(gdb) b *main+16
Breakpoint 1 at 0x8064
(gdb) r
Starting program: /root/exam6/a.out 

Breakpoint 1, 0x00008064 in main ()
(gdb) info reg
r0             0x0	0
r1             0xa	10
r2             0x14	20
r3             0x1e	30
r4             0xbefffcb0	3204447408
r5             0x0	0
r6             0x0	0
r7             0x0	0
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x0	0
r12            0x0	0
sp             0xbefffcb0	0xbefffcb0
lr             0x0	0
pc             0x8064	0x8064 <main+16>
cpsr           0x10	16
(gdb) x/x 0xbefffcb0
0xbefffcb0:	0x00000001
(gdb) ni
0x00008068 in main ()
(gdb) x/4x 0xbefffcb0
0xbefffcb0:	0x00000001	0xbefffdc9	0x00000000	0xbefffddb
(gdb) x/4x 0xbefffca4
0xbefffca4:	0x0000000a	0x00000014	0x0000001e	0x00000001
(gdb) ni
0x0000806c in main ()
(gdb) ni
0x00008070 in main ()
(gdb) ni
0x00008074 in main ()
(gdb) disas main 
Dump of assembler code for function main:
   0x00008054 <+0>:	mov	r1, #10
   0x00008058 <+4>:	mov	r2, #20
   0x0000805c <+8>:	mov	r3, #30
   0x00008060 <+12>:	mov	r4, sp
   0x00008064 <+16>:	push	{r1, r2, r3}
   0x00008068 <+20>:	eor	r1, r1, r1
   0x0000806c <+24>:	eor	r2, r2, r2
   0x00008070 <+28>:	eor	r3, r3, r3
=> 0x00008074 <+32>:	ldmdb	r4, {r1, r2, r3}
End of assembler dump.
(gdb) info reg
r0             0x0	0
r1             0x0	0
r2             0x0	0
r3             0x0	0
r4             0xbefffcb0	3204447408
r5             0x0	0
r6             0x0	0
r7             0x0	0
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x0	0
r12            0x0	0
sp             0xbefffca4	0xbefffca4
lr             0x0	0
pc             0x8074	0x8074 <main+32>
cpsr           0x10	16
(gdb) ni
Cannot access memory at address 0x0
0x00008078 in ?? ()
(gdb) info reg
r0             0x0	0
r1             0xa	10
r2             0x14	20
r3             0x1e	30
r4             0xbefffcb0	3204447408
r5             0x0	0
r6             0x0	0
r7             0x0	0
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x0	0
r12            0x0	0
sp             0xbefffca4	0xbefffca4
lr             0x0	0
pc             0x8078	0x8078
cpsr           0x10	16

댓글

Designed by JB FACTORY