일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- compare
- 유효 주소
- WPF
- instruction
- assembly
- GCC
- C#
- effective address
- 어셈블리
- sib
- struct
- struct반환
- modr/m
- movaps
- call instruction
- C
- OS
- return
- disassemble
- 숏코딩
- stackalign
- movups
- C언어
- movdqu
- csproj
- 운영체제
- modrm
- void main
- NASM
- load effective address
- Today
- Total
목록전체 글 (24)
프로그래밍 잡화점
어셈블리 기본 Instruction중 하나인 LEA(Load Effective Address)에 대해 알아보자.Effective Address가 무엇인가?예전에 어셈블리와 기계어에 대한 포스트에서 언급한 바 있는 SIB란 녀석이 있었다. Base + Scale * Index로 계산되는데, 여기에 Displacement까지 더해서 나온 주솟값.이 주솟값을 Effective Address, 한국어론 유효 주소라고 부른다. 그렇다면 어셈블리에서 LEA는 주로 어디에 사용되는가? 가장 간단한 예시로는 특정 레지스터의 주소를 기반으로 다른 주소를 구할 때 사용할 수 있을 것이다. 예를 들어, 가장 간단한 함수에서 사용하는 변수에 접근한다고 생각해보자.그럼 다음과 같은 코드를 작성할 수 있을 것이다.... ..
최근 어셈블리를 사용하던 도중 왜 돌아가지 라는 생각이 드는 코드가 있었다. mov eax, [arr+edx*3] 엥? 뭐가 문제인데요? 이전 글을 참고해 보자. Scale의 경우에는 보이다 싶이 1, 2, 4, 8만 사용될 수 있다. 그렇다. Instruction 상에는 저런 SIB가 존재할 수 없다는 얘기다. 가장 간단한 방법을 통해 어떤일이 벌어졌는지 알아보자. gdb로 빌드된 파일을 역어셈 해보았더니 맞다. 눈치 빠른 사람은 벌써 눈치를 챘을 텐데 원래 우리가 해석할려고 했던 것에서 뭐가 문제인지 알아냇을 것이다. 저 코드를 이상하다고 보고 해석했다면, arr을 base, edx를 index, 3을 scale로 해석했을 것이다. arr을 base로 두어야 하는가? ModR/M에서 SIB 형태만 존..
이번에 알아볼 것은 Call 이다. 간단하게 생각해서 C에서의 함수 호출이라고 볼 수 있다. 어셈블리에서 특정 위치로 분기하는 방법엔 여러가지가 있다. Jmp instruction을 사용할 수도 있고 IP(Instruction Pointer) register를 변경할 수도 있다. 그리고 이번에 알아볼 Call도 분기라고 볼 수도 있을 것 같다. C 함수를 먼저 생각해보자. C에서 함수를 호출하면 무슨일이 벌어질까? 일단 기본적으로 함수는 이름(주소)과 매개변수, 그리고 종료(return)을 기본 틀로 잡는다. 함수가 이름으로 호출될때 매개변수를 받을 수 있으며, 함수의 내용이 끝난 뒤에 return을 통해 다시 호출자에게 반환된다. 또한, C의 함수 내부엔 "지역변수"라는 것도 존재한다. 자, 이제 어셈..
최근 IR -> Binary 프로젝트를 작업하면서 Instruction이 Byte코드로 변환되는 과정을 공부했었다. 여러 블로그와 인텔 문서까지 봤는데 좀 쉽게 설명하면서 내용을 정리하고자 올린다. (Intel® 64 and IA-32 Architectures Software Developer Manuals < Intel 메뉴얼) (http://ref.x86asm.net/coder.html < opcode 목록 *AVX 미포함* ) 어셈블리와 기계어가 왜 1:1 대응인지 알아보러 가보자 Instruction Format Instruction의 구조는 간단하면서도 생각외로 복잡하다. 다음 표를 보자 Instruction 하나에 많은 것들이 들어가는데 앞에서부터 천천히 살펴보자 Instruction Pref..
4. 비트 연산자 비트 연산에도 생각보다 많은 명령어가 존재하지만, 기본적인 것만 알아보고 가자. shl, shr, not, and, or, xor 사용법은 간단하다. not을 제외하고 operand를 2개 갖는다. not은 1개의 operand를 갖는다. shl 은 shift left의 약자로 C에서 와 같다. 나머지 연산자의 경우에는 일반적으로 아는 그 연산자들이다. 5. 조건과 분기 이제 가장 많이 쓰게 될 조건과 분기에 대해서 알아보자. call도 분기에 속하지만, 설명할 내용이 많아 나중에 설명할려고 한다. 일단 조건문을 구성할 때 쓰이는 녀석엔 두가지가 있다. cmp와 test란 녀석인데 cmp는 이름부터 유추할 수 있듯이 compare의 약자이다. cmp op1, op2 cmp가 if라고 생..
오늘 할 것은 Assembly에서 "직접" SIMD를 사용해보는 것이다. (구글링과 직접 실험을 통해 얻은 지식을 바탕으로 한 것이기 때문에 더 효율적이고 보편적인 코드가 있을 수 있음) 가끔 프로그램을 분해 해보면 movups같은 이상한 instruction들이 보이곤 하는데, SIMD랑 연관이 있는 명령어 였다. SSE의 경우 xmm이란 128 레지스터를 사용하는데 값을 xmm에 로드하기 위해서 사용되는 명령어가 바로 movups, movaps, movdqa, movdqu가 있다. (이 외에도 꽤 많은 명령어가 있다) 이런 명령어를 통해서 xmm에 값을 로드할 수 있는데 SIMD를 사용할 땐 아주 중요한게 하나 있다. 바로 align을 맞춰야 한다는 것. stack align에 대해서 간단하게 설명하..
함수의 반환에 대한 고찰 오늘은 함수 반환에 대해 간단하게 알아보고자 한다. * 컴파일 옵션은 다음과 같다 gcc -o Main Main.c -O0 보통 함수에서 값을 반환하게 되면, eax(32bits), rax(64bits) 레지스터를 사용하게 된다. 그리하여 thinkcs.tistory.com 예전이 이런 포스팅을 한적이 있었다. 어셈블리를 사용하면서 얻은 지식이 있어 추가적으로 보완하고자 글을 쓰게 되었다. struct를 반환하게 되면 어셈블리에선 어떠한 일이 일어나는가? 에 대해서 알아보도록 하자 일단 먼저 struct는 레지스터에 들어갈 수 있는 크기가 아니다 보니 값 그 자체로 반환되지는 않는다. 보통 struct를 반환하는 함수 내에서 어딘가에는 struct를 선언하는 코드가 존재한다. 즉..
오늘은 함수 반환에 대해 간단하게 알아보고자 한다. * 컴파일 옵션은 다음과 같다 gcc -o Main Main.c -O0 보통 함수에서 값을 반환하게 되면, eax(32bits), rax(64bits) 레지스터를 사용하게 된다. 그리하여 main에서 int를 반환할때도 eax나 rax에 exit_code를 전달해서 main을 탈출하게 되는데. 여기서 한가지 의문이 생기게 된다. 그렇다면 구조체 같이 복잡한 구조의 타입을 반환하면 어떻게 될까? 다음과 같이 한 구조체를 만들고 컴파일을 한 뒤 어셈블리 코드로 뜯어보았다 typedef struct { int a, b, c; } A; A test() { A a = { 1, 2, 3 }; return a; } int main() { A a = test(); r..
어셈을 통한 구조 분석을 하기 위해서는 먼저 역어셈된 파일을 분석할 줄 알아야 한다. 이에 이번 포스팅에서는 문법과 자주 보이는 명령어들을 알아볼 것이다. 이전 포스팅에서도 말했듯이 intel nasm을 기반으로 작성하였다. (* 분석을 위한 설명 위주로 진행하며, 추후 가능하다면 어셈블리 강좌를 만들때 자세히 설명 할 생각이입니다) Syntax x86/x64 nasm 어셈블리는 기본적으로 다음과 같은 구조를 지닌다 section .data ; 초기값을 갖는 전역 변수 선언 section .bss ; 비어있는 전역 변수 선언 section .text ; 함수를 외부에 노출 ; ld링킹의 경우 _start를 사용 ; gcc링킹의 경우 main을 사용 global _start ; _start 레이블 _sta..
어셈블리를 통한 C 컴파일러의 해석 구조를 알아보자. 기본적인 분석을 위해 알아야 할 기본 지식들을 알아보고 가보자. 들어가기 앞서 문법은 nasm, intel을 사용하며, arm은 다루지 않을 예정입니다. (arm은 intel이랑 문법이 다르며 구조도 좀 달라 intel과 함께 포스팅하기 어렵습니다) 레지스터란? 아주 작은 메모리 공간인데, cpu와 붙어 있어 매우 빠른 속도로 동작이 가능하다. 레지스터의 종류는 이 블로그를 참고해보자 범용 레지스터 주로 값 이동과 반환 값을 갖는 레지스터(AX, BX, CX, DX)는 특이한 성질이 있다 AL, AH, AX, EAX, RAX로 5가지 종류가 존재하는데 이들은 각각 큰 레지스터를 공유하여 사용한다. AL과 AH는 각각 8비트, 즉 1바이트의 크기이다 A..