You must write 64 bits ASM. Beware of the "calling convention".
: ISA(Instruction Set Architecture)는 명령어 종류, 피연산자 타입, 레지스터 개수, 인코딩 방법 등 여러 가지를 정의한다.
그외에 실제로 프로그램이 돌아가려면 ISA 위에 ABI(Application Binary Interface)라는 응용프로그램과 운영체제 사이의 약속도 필요하다.
함수호출규약(calling convention)이나 바이너리 포맷에 대한 규약이 대표적이다.
출처: 프로그래머가 몰랐던 멀티코어CPU 이야기
cdecl
규칙을 따른다.참조You can’t do inline ASM, you must do ’.s’ files.
s
확장자는 어셈블리코드를 나타내는 확장자gcc -S main.c
하면 main.s가 어셈블리코드로 만들어짐.// https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html#Overall-Options
-S
Stop after the stage of compilation proper; do not assemble. The output is in the form of an assembler code file for each non-assembler input file specified.
By default, the assembler file name for a source file is made by replacing the suffix ‘.c’, ‘.i’, etc., with ‘.s’.
Input files that don’t require compilation are ignored.
- 64bit 레지스터를 가진 CPU가 처리할 수 있는 어셈블리어를 intel문법으로 작성하여라.
- 이 때 함수 호출 규칙을 지켜야 한다. c언어에 맞는 호출 규칙을 지키자.
- 함수가 실행되면서 처리되는 레지스터는, 42환경에 맞춰야겠지?(macOS, 64bit)
어셈블리어
이다.global _start
선언으로 시작해야 함. section.text
global _start
_start:
[label] mnemonic [operands] [;comment]
INC COUNT ; Increment the memory variable COUNT
MOV TOTAL, 48 ; Transfer the value 48 in the
; memory variable TOTAL
ADD AH, BH ; Add the content of the
; BH register into the AH register
AND MASK1, 128 ; Perform AND operation on the
; variable MASK1 and 128
ADD MARKS, 10 ; Add 10 to the variable MARKS
MOV AL, 10 ; Transfer the value 10 to the AL register
명령어 dest source
[]
로 표현r8 ~ r15
_start:
가 기본의 [label]에 해당 함.[label]:
하위 전체 코드가 포인터가 된다.; ----------------------------------------------------------------------------------------
; Writes "Hello, World" to the console using only system calls. Runs on 64-bit macOS only.
; To assemble and run:
;
; nasm -fmacho64 hello.asm && ld hello.o && ./a.out
; ----------------------------------------------------------------------------------------
global start
section .text
start: mov rax, 0x02000004 ; system call for write
mov rdi, 1 ; file handle 1 is stdout
mov rsi, message ; address of string to output
mov rdx, 13 ; number of bytes
syscall ; invoke operating system to do the write
mov rax, 0x02000001 ; system call for exit
xor rdi, rdi ; exit code 0
syscall ; invoke operating system to exit
section .data
message: db "Hello, World", 10 ; note the newline at the end
instruction | operand | 설명 |
---|---|---|
mov | rax, 0x02000004 | rax레지스터에 write함수를 호출하는 syscall번호(0x02000004) 저장 |
mov | rdi, 1 | rdi레지스터에 첫번째 인자 값1(표준 출력)을 저장. write(1, ?, ?) 상태. rdi인 이유는 아키텍처에서 파라미터를 저장하는 순서가 rdi부터이기 때문 |
mov | rsi, message | 2번째 인자를 rsi에 저장. message는 data section에 선언 및 정의 됨. 즉, write(1, message, ?) 상태 |
mov | rdx, 13 | 3번째 인자를 rdx에 저장. 정수 13은 문자열 크기. 즉, write(1, message, 13)을 호출할 수 있음. |
syscall | rax에서 호출할 함수를 가져온다(write). 필요한 인자 값은 저장한 레지스터 순서대로 가져온다. (가져오면서, 해당 레지스터의 값은 pop되겠지?) | |
mov | rax, 0x02000001 | rax레지스터에 exit함수를 호출하는 syscall번호 저장. |
xor | rdi, rdi | rdi레지스터에 exit함수의 첫번째 인자 값을 저장. rdi <- rdi xor rdi 가 된다. xor연산자이기 때문에 항상 0의 값을 가진다.근데 왜 구지 xor썻는진 몰겠다.. 쨋든 exit(0)은 정상종료 의미. |
syscall | rax에서 호출할 함수를 가져온다.(exit) 역시 동일하게 인자값이 필요하면 레지스터에 저장하는 순서대로 가져오면 된다. (0)을 rdi에 저장해주었으니 잘 가져 올 것이다. | |
message | 변수 | db는 declare Byte의미 -참조 , 10은 아스키코드 개행문자(line feed)를 의미한다. message 변수는 "Hello, World" 뒤에 개행(10)을 붙여서 해석될 것이다. |
-S
이전 함수
가 호출된 시작 위치를 저장한다.레지스터에 저장 된 위치로 한방에 복귀
한다.최초 ebp레지스터에는, main함수가 호출 된 위치
가 기록된다.push ebp
=> stack에 main시작위치 저장.mov ebp, esp
해준다.push ebp
=> stack에 fn1()이 호출된 메모리 주소를 저장.mov ebp, esp
해준다.mov esp, ebp
=> 현재 sp값을 fn2() 호출한 위치로 변경pop ebp
=> stack의 값을 pop해서 ebp에 넣어준다.arch x86_64 [명령어]
와 같이 사용하면 된다.lipo -archs 실행파일명
nasm -f macho64 ft_strlen.s
gcc -c main
하여 목적파일 생성.gcc *.o
수행ld: warning: ignoring file ft_strlen.o, building for macOS-arm64 but attempting to link with file built for unknown-x86_64
Undefined symbols for architecture arm64:
"_ft_strlen", referenced from:
_main in main.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
x86_64
아키텍처로 생성.arch -x86_64 gcc -c main.c
x86_64
아키텍처의 실행파일 생성arch -x86_64 gcc *.o
ld hello.o -o hello -macosx_version_min 11.0 -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem