본문으로 바로가기




[ 1. 기본적인 차이 ]

일단, 비트가 무슨 의미인지 알아보자.

비트 ( bit )란, 2진수 0과 1을 포함할수있는 크기를 말한다.

이러한 비트가 2^3 ( 8 )개가있으면 바이트 ( byte ) 이다.

이러한 바이트가 2^10 ( 1024 )개 있으면 킬로바이트 ( kbyte ) 이다.

이러한 킬로바이트가 2^10 ( 1024 )개 있으면 메가바이트 ( mbyte ) 이다.

이러한 메가바이트가 2^10 ( 1024 )개 있으면 기가바이트 ( gbyte ) 이다.

:

:


32 bit 운영체제는, 이러한 비트를 2^32 만큼 사용하는 운영체제이고, 64 bit는 이러한 비트는 2^64 만큼 사용한다.

32 bit 운영체제는 메모리를 0부터 4,294,967,296 만큼 저장할수있고,

64 bit 운영체제는 메모리를 0부터 18,446,744,073,709,551,616 만큼 저장할수있다.


또한, 사용하는 메모리 ( RAM )의 용량에도 제한이 있는데, 32bit 컴퓨터에서는 RAM이 최대 4gb까지 들어간다.

32bit 컴퓨터에서 아무리 많은 용량의 ram을 달아봤자, 결국에는 4byte ram의 효과만 보는것이다.

64bit 컴퓨터에서는 최대 1tb ( 2^10 gb) 만큼의 RAM이 들어간다.








[ 2. 사용하는 레지스터의 차이 ]

32비트에서는 8개의 범용 레지스터를 사용한다. ( EAX,ESP,EBP 등등.. )

64비트에서는 레지스터가 4바이트 ( 32 bit ) 에서 8바이트 ( 64 bit ) 로 나뉜다.

그리고 레지스터의 용량이 클수록 메모리에서 더 많은 데이터를 가져와 저장할 수 있어서 처리속도도 빨라진다.

  ● 8 bit Register : AH, AL    => H(High), Low(Low) 접미사가 붙는다.
  ● 16bit Register : AX        => AH와 AL이 합쳐졌다.
  ● 32bit Register : EAX      => AX가 확장되어 E(Extend) 접두사가 붙었다.
  ● 64bit Register : RAX      => 접두사 E가 R로 변경되었다.(R이 Register를 뜻한다는 말이 있지만 정확하지 않다.)


비트별 운영체제의 레지스터는 위와같다.















[ 3. 함수 호출 규약의 차이 ]

32비트에서는 8개의 범용 레지스터를 사용한다. ( EAX,ESP,EBP 등등.. )

64비트에서는 레지스터가 4바이트 ( 32 bit ) 에서 8바이트 ( 64 bit ) 로 나뉜다.

그리고 레지스터의 용량이 클수록 메모리에서 더 많은 데이터를 가져와 저장할 수 있어서 처리속도도 빨라진다.

  ● 8 bit Register : AH, AL    => H(High), Low(Low) 접미사가 붙는다.
  ● 16bit Register : AX        => AH와 AL이 합쳐졌다.
  ● 32bit Register : EAX      => AX가 확장되어 E(Extend) 접두사가 붙었다.
  ● 64bit Register : RAX      => 접두사 E가 R로 변경되었다.(R이 Register를 뜻한다는 말이 있지만 정확하지 않다.)


비트별 운영체제의 레지스터는 다음과 같다.


64비트에서 환경에서는 rax, rbx, rcx, rdx, rbp, rsp, rsi, rdi 에다가 8개의 레지스터를 추가로 가진다.

8개의 레지스터는 (r8 ~ r15) 이다.


리눅스는 System V AMD64 ABI라는 함수호출 규약을 따른다.

여기 정의된 바에 의하면, 함수를 호출할때 최초 6개의 정수/포인터 인자는 

rdi, rsi, rdx, rcx, r8, r9를 통해 순서대로 넘겨지고, 그 이상의 매개변수가 전달돼야 할 땐 스택을 통해 전달한다.

실수인자는 xmm0 ~ xmm7 까지 8개의 레지스터를 순서대로 사용하여 전달하고 그 이상이면 스택을 통한다.


반환 값은 정수일때 rax(하위 64비트), rdx(상위 64비트) 를 사용하고

실수일때는 xmm0(하위 128비트), xmm1(상위 128비트) 를 사용한다.


위 그림을 통해 지금까지 설명한 내용을 이해해보자.


인자는 32bit처럼 뒤에서부터 전달된다.






[ 4. cdecl, stdcall, fastcall 함수 호출 규약 ]

일단, 함수 호출 규약은 함수를 call하는쪽에서 스택을 정리할지, 함수에서 stack을정리할지에 대한 규약이다.


cdecl은 call(호출자)에서 stack을 정리하는것을 말한다.

인자를 오른쪽에서 왼쪽으로 넣으며, 장점은 가변인자 전달이 가능해진다.

함수앞에 _ 을 추가하여 알아볼수있다.


stdcall cdecl의 반대개념이다. stdcall은 stdcall형식으로 asm을 컴파일할때 규약을 따르는 코딩이다.

=> 함수에서 스택을 정리하고 함수를 빠져나옴

인자를 오른쪽에서 왼쪽으로 넣으며, 장점은 코드 길이가 짧아진다.

함수앞에 _ 를 추가하고, 이름뒤에는 @를 추가한다.


fastcall은 기본적으로 stdcall와 같다.

하지만 처음 두 인자는 ECX와 EDX에 넣고 나머지는 오른쪽에서 왼쪽 순으로 인자를 전달한다.

장점은 빠른 함수 호출이다.

스택 정리는 호출된 함수에서 한다.

함수 앞에 @를 추가하고, 이름 뒤에는 @가 추가된다. 스택 이용 바이트수를 표현한다.




그리고 마지막.

ROP할때는


<32 bit>

함수 호출 -> pr -> 인자 

<64 bit>

pr -> 인자 -> 함수 호출


이런 차이가 있다.