728x90

 

_strlen 를 퉁해 문자열의 길이를 r10레지스터에 저장한다.

이후 _strcpy에서 rcx에 r10 즉 입력한 문자열의 길이를 넘겨주고

rsi에 입력한 문자열, rdi에는 복사할 문자열 주소를 넣어준다.

 

rep movsb는 rsi를 rdi로 1byte씩 ecx값만큼 데이터를 옮기는 명령어이다.

한번 동작할때마다 ecx는 -1이 되며 0이되면 더이상 줄어들지않고 다음 명령어를 실행시킨다.

실행화면

 

728x90

'Programming > assembly' 카테고리의 다른 글

nasm x64 assembly memcpy 구현  (0) 2020.03.16
nasm x64 assembly strcmp 구현  (0) 2020.03.15
nasm x64 assembly strcpy 구현 -1  (1) 2020.03.11
inline func alloca  (0) 2020.03.10
nasm x64 assembly strlen 구현  (0) 2020.03.10
728x90

strcpy를 구현해 봤다.

bss영역에 1024크기의 문자열 string1, string2를 선언해준다.

이후 sysread를 통해 string1에 문자열을 입력해주고 _strcpy를 호출한다.

_strcpy에서는 lea를통해 rsi로 옮긴 string1에 1바이트씩 접근하여 al로 데이터를 옮긴 후 string2에 데이터를 쓰고 있다. 

 

이후 _print 를 통해 데이터를 복사된 문자열을 출력한다.

strcpy 실행화면

 

728x90

'Programming > assembly' 카테고리의 다른 글

nasm x64 assembly strcmp 구현  (0) 2020.03.15
nasm x64 assembly strcpy 구현 -2  (0) 2020.03.11
inline func alloca  (0) 2020.03.10
nasm x64 assembly strlen 구현  (0) 2020.03.10
loop  (0) 2020.03.01
728x90

alloca.c

alloca함수는 스택에 함수를 할당해주는 함수이다. malloca 스택버전?

지인 과제로 alloca를 gdb로 열어보았다.

aclloca 디스어셈블리

alloca함수는 inline함수로 따로 함수를 호출하지않아 gdb로 분석시 어셈블리 코드가 그대로 들어가있다.

alloca는 동작 과정에서 alloca로 입력한 인자 위코드에서는 5000 +31을 하고 16으로 나눈 값에 16을 곱하여 16보다 작은 수는 버려서 16으로 aligned 시켜준다. 입력한 인자보다 무조건 큰 스택영역이 할당된다.

728x90

'Programming > assembly' 카테고리의 다른 글

nasm x64 assembly strcpy 구현 -2  (0) 2020.03.11
nasm x64 assembly strcpy 구현 -1  (1) 2020.03.11
nasm x64 assembly strlen 구현  (0) 2020.03.10
loop  (0) 2020.03.01
어셈블리 문법  (0) 2020.03.01
728x90

어셈블리로 strlen 을 구현해 봤다.

 

strlen의 경우 al 즉 8bit 1byte씩 문자들을 '\n'와 비교하여 문자열 끝을 찾았다.

sys_read를 통해 문자열을 입력하니 fgets 처럼 '\n'이 문자열에 포함되어있었다.  

bss영역인 string에서도 직접 1byte씩 메모리에 접근하여 모든 문자열을 1byte씩 비교할 수 있었다.

 

strlen 구현은 무난했지만 printf함수 호출에서 오히려 더 어려움을 느꼇던것 같다.

단순히 호출하면 되는 줄 알았지만 스택 메모리 주소가 맞지않아 rsp를 조정후에 호출해주었다.

 

printf함수 내부적으로 movaps를 호출하는데 여기서 스택메모리가 16 단위로 aligned 되어야하는것이다.

디버깅 후에 add rsp, 8을 통해 16단위로 stack memory를 aligned 해주어 printf호출에 성공했다.

 

728x90

'Programming > assembly' 카테고리의 다른 글

nasm x64 assembly strcpy 구현 -1  (1) 2020.03.11
inline func alloca  (0) 2020.03.10
loop  (0) 2020.03.01
어셈블리 문법  (0) 2020.03.01
echo  (0) 2020.03.01
728x90

loop.s

반복문은 again에 해당하는 곳이다.

 

_start부터 코드를 보면

rax,1  rdi,1 rsi,msg rdx 1등을 통해 sys_write(1,msg,1)을 호출할 준비를 하고있다. r10은 범용 레지스터로 어느 목적이든 사용가능한 레지스터이다. 

 

again을 보면 r10과 100을 비교한다. je done 명령어는 cmp를 통해 비교한 양쪽값이 같으면 done을 호출한다는 의미이다. 두개의 값이 같지않으면 syscall을 통해 msg 'A'를 출력하게 된다. 이후 rax에 1을 넣음으로써 sys_write를 호출할 준비를 해주고 r10의 값을 1증가시켜준다. inc 명령어는 해당 레지스터의 값을 1올려주는 명령어이다. jmp again을 통해 반복을 해준다. 문자열 출력과 r10값 증가가 100번 반복하여 r10과 100의 값이 같아지면 done으로 이동한다.

 

done 은 sys_exit를 호출한다. 프로그램을 종료시킨다.

728x90

'Programming > assembly' 카테고리의 다른 글

inline func alloca  (0) 2020.03.10
nasm x64 assembly strlen 구현  (0) 2020.03.10
어셈블리 문법  (0) 2020.03.01
echo  (0) 2020.03.01
sum.c 스택 프레임  (0) 2020.03.01
728x90

 

mov dst, src : src의 값을 dst로 넘긴다. ex) mov eax, 100 -> 100을 eax에 저장한다.

 

LEA dst, src : LEA는 특정 배열에 접근할려고 할때 많이 사용한다. 연산을 포함하여 복사가능하다. ex) LEA EAX, EAX+1000 -> eax에 1000을 더한값을 다시 eax에 삽입한다.

ex) LEA EAX, [EAX+1000] -> [ ]대괄호는 어셈블리에서 주소가 가리키는 값을 의미한다. 즉 EAX에서 1000을 더한 주소가 가리키는 값을 EAX에 넣어라 라는 의미의 명령어가 된다.

 

JMP : 특정 위치로 건너뛰어 코드를 실행시킨다.

 

CALL : 함수 호출을 위해 사용된다. JMP를 통해 해당 함수로 이동하여 명령어 실행후 함수종료후 RET을 통해 돌아온다.

CALL은 JMP와 다르게 다시 돌아오는 RET이 포함되어있다.

 

NOP : 아무작업도 하지않는 명령어이다. 1Byte 공간을 차지한다.

 

RET : 현재 함수가 끝난 뒤에 돌아갈 주소를 지정하기 위해 사용한다.

 

PUSH : 스택에 해당값을 저장할때 사용된다.

 

POP : 스택에 있는 값을 가져올때 사용된다.

 

LEAVE : 현재까지의 메모리 스택을 비우고 EBP를 자신이 호출한 메모리 주소로 채운다.

 

nasm은 문자와 문자열을 구분하지 않는다.

 

db 'hello' 와 db 'h','e','l','l','o'는 같다.

 

msg db 'Hello World!!!',10,00

은 Hello World!!! 개행 문자열 종료 와 같다.(10은 \n , 00은 NULL이다.)

 

위에서 msg는 변수명이아니라 레이블이다. 레이블은 주소를 가리키는 주소의 표현이라고 생각하면 된다.

 

 

 

 

 

 

 

 

 

 

 

어셈블리 컴파일

 

 

목적파일 생성

nasm -f elf64 -o abc.o abc.s

 

실행 파일

ld -o abc abc.o

 

어셈블리 소스코드 마지막에

mov rax, 60

syscall

을 넣어주지 않으면 세그멘테이션 오류 발생 

 

728x90

'Programming > assembly' 카테고리의 다른 글

nasm x64 assembly strlen 구현  (0) 2020.03.10
loop  (0) 2020.03.01
echo  (0) 2020.03.01
sum.c 스택 프레임  (0) 2020.03.01
메모리 구조  (0) 2020.03.01
728x90

 

echo.s

xor rax, rax를 통해 rax를 0으로 설정해주고 rdx, rcx, rdx 또한 0으로 설정해준다.

rsp를 64만큼 확장하여 문자열 저장공간을 확보한다.

 

rax, 0 sys_call number 0번은 sys_read이다. 파일을 읽어들이는 함수인다. rdi 0을 통해 fd를 0으로 설정해주어 stdin이 가능하다. 즉 키보드 입력이 가능한 것이다. 이후 rsi에는 저장될 공간 rsp를 넣어주고 rdx에는 저장가능한 문자열 공간 63을 넣어준다. 64를 확장해주고 NULL이 들어갈 공간을 위해 rdx에는 63을 넣어준 것이다.

 

이후 rax, 1을 통해 syscall sys_write를 호출할 준비를 하고 rdi에 1을 넣음으로써 fd를 1로 설정하여 stdout이 가능하게 한다. 저장되어있는 문자열 주소인 rsp를 인자로 넣어주고 출력 크기인 63을 넣어준다.

syscall을 통해 화면에 문자열을 출력해준다.

 

60번 syscall 인 sys_exit을 통해 프로그램을 종료시켜준다.

echo 실행화면

입출력은 sys_read 와 sys_write로 가능하다.

rsp의 값 확장은 sub rsp, 확장할 크기 로 가능하다.

스택은 주소상 위에서 아래로 자라기 때문이다. sub로 값을 빼준만큼 스택공간이 확장된다.

728x90

'Programming > assembly' 카테고리의 다른 글

loop  (0) 2020.03.01
어셈블리 문법  (0) 2020.03.01
sum.c 스택 프레임  (0) 2020.03.01
메모리 구조  (0) 2020.03.01
Hello World (x64)  (0) 2020.03.01
728x90

sum.c

위 코드의 스택프레임을 정리할려고 한다.

RET이 스택의 가장 아래쪽이다.(스택이 위로 쌓인다고 가정할때) (스택은 주소값상에서는 위에서부터 아래로 쌓인다.)

RET(return address)은 함수종료후 돌아갈 주소를 가리킨다.

main함수 실행 전 _start가 실행되고 _start에서 main을 호출하는데 main함수가 종료되면 다시 _start로 돌아온다. 이때 돌아가는 주소가 RET에 저장되어 있다.

 

함수의 BASE포인터가 RET 바로위에 저장되고 RBP 이후로 지역변수들이 차례로 저장된다. 변수 C가 RBP바로 위에 저장된 모습이다.

 

sum 호출 후 스택프레임

함수를 호출할 때 그함수의 매개변수는 그함수의 RET 아래에 저장된다.

sum을 호출할때 매개변수 x, y가 sum의 ret 아래에 저장된 모습이다.

 

sum 함수가 종료되면 변수 X ~ RBP, 버퍼 까지 모든 스택들이 사라진다. 그리고 변수 C에는 3이 들어간다.

 

sum 함수 종료 후 스택 프레임

sum의 반환을 통해 변수 C에 3이 저장된 형태이다. 메인함수가 종료되면 3도 main함수가 호출된 곳으로 반환한다.,

 

RET의 경우 함수 종료 후 돌아가는 메모리 주소가 저장되어있다. bufferover flow를 통해 ret을 조정하여 임의로 원하는 주소로 이동이 가능하다.

 

728x90

'Programming > assembly' 카테고리의 다른 글

어셈블리 문법  (0) 2020.03.01
echo  (0) 2020.03.01
메모리 구조  (0) 2020.03.01
Hello World (x64)  (0) 2020.03.01
어셈블리 기초(x86)  (0) 2020.03.01

+ Recent posts