ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [libasm] 01. 기초지식 - 리눅스의 호출 규약과 어셈블리코드 정리
    과제/libasm 2021. 2. 24. 22:28

    1. 호출규약

    윈도우와 리눅스의 호출규약은 서로 다르다.

    출저 : https://kkamagui.tistory.com/811

     

     

     

    출처: Paul A. Carter의 [PC 어셈블리어]에서 1.3.4 

    출처: nasm 어셈블리 산술 연산 

    출처: movsx, movzx

    MOV MOV dest, src -> src에 있는 데이터를 dest에 복사  
    ADD 정수 a, b 일때 a + b  
    SUB 정수 a, b 일때 a - b  
    INC INC dest -> dest를 1 증가 시킨다. dest++ 기계코드 크기가 ADD, SUB보다 더 작다.
    DEC DEC dest -> dest를 1 감소 시킨다. dest– 기계코드 크기가 ADD, SUB보다 더 작다.
    MUL MUL multiplier 부호 없는 데이터를 곱합니다.  
    IMUL IMUL multiplier Integer mul. 부호 있는 데이터를 곱합니다.  
    DIV    
    IDIV    
    movzx dst가 src보다 큰 공간이어도 복사가 되고, 남는 공간은 0으로 채워진다. 부호가 없는 정수에만 사용
    movsx 남는 공간이 1로 채워진다. 부호가 있는 정수에만 사용한다
      *참고: 부호비트 자리가 1이라는 것은 컴퓨터에게 ‘음수거나 부호가 있는 정수’라는 뜻이다.  
      그니까 왜냐면.. 음수(부호가 있는 수)계산은 사실은 항상 보수처리해서 더하기로 진행하니까..?  

    출처:  댕이댕이의 Network 블로그! - 리버싱 기초

     

     

    64bit NASM Assembly Register

    Name Notes Type 64-bit
    long
    32-bit
    int
    16-bit
    short
    8-bit
    char
    rax Values are returned from functions in this register.   scratch rax eax ax ah and al
    rcx Typical scratch register.  Some instructions also use it as a counter. scratch rcx ecx cx ch and cl
    rdx Scratch register. scratch rdx edx dx dh and dl
    rbx
    Preserved register: don't use it without saving it! preserved rbx ebx bx bh and bl
    rsp
    The stack pointer.  Points to the top of the stack (details coming soon!) preserved rsp esp sp spl
    rbp
    Preserved register.  Sometimes used to store the old value of the stack pointer, or the "base". preserved rbp ebp bp bpl
    rsi Scratch register used to pass function argument #2 in 64-bit Linux.  In 64-bit Windows, a preserved register. scratch rsi esi si sil
    rdi Scratch register and function argument #1 in 64-bit Linux.  In 64-bit Windows, a preserved register. scratch rdi edi di dil
    r8 Scratch register.  These were added in 64-bit mode, so they have numbers, not names. scratch r8 r8d r8w r8b
    r9 Scratch register. scratch r9 r9d r9w r9b
    r10 Scratch register. scratch r10 r10d r10w r10b
    r11 Scratch register. scratch r11 r11d r11w r11b
    r12
    Preserved register.  You can use it, but you need to save and restore it. preserved r12 r12d r12w r12b
    r13
    Preserved register. preserved r13 r13d r13w r13b
    r14
    Preserved register. preserved r14 r14d r14w r14b
    r15
    Preserved register. preserved r15 r15d r15w r15b

    위 표는 어떨때 쓰냐면, 여기 과제에서는 대부분 char 형(8-bit) 를쓰기 때문에, 내가 만약에 rax가 가르키는 주소에서 char를 읽어서 다른 레지스터에 넣는다 하면

    mov rcx, BYTE [rax]  이런식으로 쓰면 rcx 는 64bit 기 때문에 에러가 난다. 따라서 rcx 에 넣고 싶으면 저 위 표를 보고

    mov cl, BYTE [rax] 이런식으로 넣어야 한다.

     

     

    syscall 와 ___error 를 통한 에러처리 (write 를 예로)

    section .text
        global _ft_write
        extern ___error
    
    _ft_write:
        mov rax, 0x2000004		syscall을 사용하기 위해 rax 에 syscall 번호를 넣어줌
        syscall					rax에 write 의 리턴값을 저장
        jc err					만약 에러가 났다면 carry flag = 1 로 바뀌므로 jc 로 체크해서 점프
        ret						아니라면 그대로 리턴
    
    err:
        push rax				write 는 에러가 났을경우 에러번호를 rax에 그대로 담아두기에 일단 푸쉬함
        call ___error			errno 을 담을 주소값을 rax에 리턴해줌
        pop rcx					write 가 push 해둔 rax의 값을 rcx 로 pop함
        mov [rax], rcx			rax 가 가르키는 주소의 값에 rcx값을 넣어줌
        mov rax, -1				rax (리턴값) 에는 -1 을 넣어줌
        ret

    처음에

    err:

    함수 부분에서 

    push rax

    call ___error

    pop rcx

     

    하지말고 

    mov rcx, rax

    call ___error 

    하면 되는것 아닌가? 했는데 ___error 에서 rcx 값에다가 무슨짓을 할지 모른다. 따라서 push 한 후 함수호출이 끝나면

    pop 하는 것이 안전하다 (라고 나는 생각했다)

Designed by Tistory.