본문 바로가기

Programming Language/Assembly

[GAS/XCode]64비트 어셈블리어에서 메모리 번지 지정 오류 해결 32비트에서는 Hello, World 구문을 아래와 같이 띄울 수 있습니다. /* 32bit version / GNU Assembly */ .data message: .string "Hello, World!\n" .text .global _main .extern _printf _main: # 스택 프레임 만들기 pushl %ebp movl %esp, %ebp # 함수의 본문 # printf(message); pushl $message xorb %al, %al call _printf addl $4, %esp # 스택 프레임 제거 movl %ebp, %esp popl %ebp ret 잠시 xorb %al, %al을 보자면… _printf 함수를 호출하기 전에 AL 레지스터의 값을 설정하는데, System V.. 더보기
호출 규약(calling convention) 정리 함수의 호출규약은 함수 호출 시 전달된 매개변수를 함수가 종료될 때 정리하는 방법으로서 cdecl, stdcall, fastcall, thiscall의 4가지가 존재합니다. 이 중 thiscall은 C++언어의 멤버함수에서 쓰이고 나머지는 C언어에서 사용됩니다. cdecl 호출 규약 먼저 cdecl은 C 함수 라이브러리에서 표준으로 쓰이는 호출규약으로 스택으로 전달한 매개변수를 함수를 호출한 위치에서 정리하는 방식입니다. 예를 들어 아래와 같은 C함수가 있습니다. int __cdecl _fn_cdecl(int a, int b) { return a+b; } 이를 어셈블리어로 다시 작성해봅니다. 시스템 기본 정수는 4바이트로 가정합니다. _fn_cdecl: sub esp, 4 ; 함수 종료 후 돌아갈 위치가.. 더보기
Visual Studio 2013에서 어셈블리어 코딩 후 실행하기 Visual Studio 2013은 MASM 어셈블러가 내장되어 있습니다. 별도의 어셈블러 등 추가 설치 없이 설정만으로 어셈블리어 프로그램을 작성할 수 있습니다. 1단계. [파일(F)]-[새로 만들기(N)]-[프로젝트(P)]를 클릭합니다. [새 프로젝트] 창에서 [Visual C++]-[Win32 프로젝트]를 선택합니다. 프로젝트 이름을 지정하고 [확인] 버튼 누릅니다. 2단계. 응용 프로그램 마법사 화면에서 응용 프로그램 종류를 [콘솔 응용 프로그램]에 두고 추가 옵션에서 [빈 프로젝트]를 선택한 후 [마침] 버튼을 누릅니다. 3단계. 이 프로젝트에서 MASM을 사용하기 위해서는 솔루션 탐색기에서 프로젝트를 선택 후 마우스 오른쪽 버튼을 누르고 [빌드 종속성(B)]-[사용자 지정 빌드(B)]를 클릭합.. 더보기
C-Style의 문자열 출력 C-Style의 문자열은 끝이 \0(NULL문자)로 끝나는 문자열을 말한다. 어셈블리어에서는 긴 문자열을 별도의 변수에 보관하였다가 int 21h-02h의 반복구문을 사용하거나 문자열을 자체적으로 출력해주는 int 21h-09h를 사용할 수 있다..model small .stack 64 .data message DB "Hello, World!", 0 ; 데이터 영역에 문자열을 정의한다. .code main proc far mov ax, @data ; ax를 거쳐서 데이터영역이 시작되는 메모리 주소를 DS와 ES 레지스터에 넣는다. mov ds, ax mov es, ax mov cx, 0 main_loop: mov ax, offset message ; message라는 이름의 문자열 데이터가 @data에서.. 더보기
산술 비교 알고리즘 - 3편. "<"와 ">=" .386 .model flat, stdcall .stack 1024 .data .code main PROC MOV AH, 99 MOV AL, 1 CMP AH, AL JL JMP_LESS; AH =AL이면 JMP_NLESS로 이동 JMP_LESS: MOV AH, 02h MOV DL, 3Ch; ASCII 문자 '' 출력 INT 21h MOV DL, 3Dh; ASCII 문자 '=' 출력 INT 21h JMP JMP_EXIT JMP_EXIT: MOV AH, 4Ch INT 21h main ENDP END main 실행 결과 AH이 AL보다 작지 않으므로 ">= " 문자가 출력됩니다. 더보기
산술 비교 알고리즘 - 2편. ">"와 "<=" .386 .model flat, stdcall .stack 1024 .data .code main PROC MOV AH, 99 MOV AL, 1 CMP AH, AL; AH - AL의 연산을 합니다. JG JMP_GREATER; AH > AL이면 JMP_GREATER로 이동 JNG JMP_NGREATER; AH 더보기
산술 비교 알고리즘 - 1편 "!="과 "==" option casemap: none ; 대/소문자를 구분하지 않습니다. .386; 386 CPU용 명령어들을 사용합니다. .model flat, stdcall; 메모리 모델은 stdcall을 사용합니다. .stack 1024; 스택의 크기는 1024 워드로 합니다. .data; 데이터 영역은 아직 없으므로 비워둡니다. .code; 코드 영역 시작 main PROC; main 프로시저 선언합니다. MOV AH, 99; AH 레지스터에 99를 넣습니다. MOV AL, 1; AL 레지스터에 1을 넣습니다. CMP AH, AL; AH - AL 연산을 하여 대소비교를 합니다. JZ JMP_EQUALS; AH - AL == 0이어서 ZF Flag가 1이 되면 JMP_EQUALS 위치로 점프합니다. JNZ JMP_.. 더보기
산술비교 명령어 모음 CMP , 위 명령은 두 정수를 빼서 대소 비교를 하라는 뜻입니다. A - B의 결과는 양수 또는 0 또는 음수 중 하나일텐데, 각 상황별로 CPU에 내장된 ZF(Zero Flag), CF(Carry Flag)라는 두 플래그에 값이 저장됩니다. 그리고 ZF, CF의 상태에 따라 몇 가지 분기 구문이 존재합니다. 분기 구문은 A와 B는 최상위 비트는 부호 비트로 쓸 것인지 여부에 따라 signed, unsigned 형으로 나뉘는데 각 명령은 다음과 같습니다. 상태 플래그 레지스터 AF (Auxiliary Flag) : 반 워드 단위로 자리수가 바뀔때 1로 설정. 예를 들어 8비트 CPU에서는 0100에서 10100이 되는 경우, 또는 11011에서 1011이 되는 경우CF (Carry Flag) : uns.. 더보기
점프 명령어 JMP 이번에는 점프 명령어를 알아보려 합니다. 점프 명령어는 프로그램 진행상 필요시 특정 위치로 프로그램의 흐름을 건너뛰는 역할을 합니다. 점프 명령어는 다음과 같이 선언합니다. 명령 1 명령 2 JMP 명령 3 명령 4 레이블: 명령 5 명령 6 JMP 명령어가 없다면 프로그램의 순서는 명령 1-2-3-4-5-6의 순차적으로 진행될 것입니다. 그러나 JMP를 통해 특정 레이블로 점프시킨다면 1-2-5-6의 순서로 진행 됩니다. 그럼, 이전에 테스트 해 보았던 헬로 월드 예제로 적용해 보죠. .386 ; 386 CPU용 명령어들을 사용합니다. .model flat, stdcall ; 메모리 모델은 stdcall을 사용합니다. .stack 1024 .data ; 데이터 영역은 아직 없으므로 비워둡니다. .cod.. 더보기
두 번째 예제: Hello, World! .386 ; 386 CPU용 명령어들을 사용합니다. .model flat, stdcall ; 메모리 모델은 stdcall을 사용합니다. .stack 1024 .data ; 데이터 영역은 아직 없으므로 비워둡니다. .code ; 코드 영역 시작 main PROC ; main 프로시저 선언합니다. MOV AH, 02h ; AH 레지스터에 문자 1개를 출력하는 명령인 02h를 넣습니다. 반복적으로 사용될 값이므로 첫 번째 예제와는 순서를 바꿔서 가장 처음에 배치해 봤습니다. MOV DL, 48h ; DL 레지스터에 아스키문자 'H' (0x48)를 넣습니다. INT 21h ; 만능 인터럽트 21h를 발생시켜 AH, DL에 담긴 내용대로 처리합니다. MOV DL, 65h ; DL 레지스터에 아스키문자 'e' (0.. 더보기
첫 예제: 1개의 문자 출력 MASM 어셈블리 코드는 다음과 같은 기본 뼈대를 갖습니다. .386 .model flat, stdcall stack segment para stack db 1024 dup(?) stack ends data segment data ends code segment main proc far main endp code ends end main 이를 좀 더 단순화하면 .386 .model flat, stdcall .stack 1024 .data .code main proc main endp end main .386 .386 지시어는 386 CPU를 위한 명령어들만 사용한다는 의미입니다. 286, 486, 586p 등 다양한 지시어를 사용할 수 있고 여기에 지정한 CPU에 따라 사용할 수 있는 명령어가 달라지고,.. 더보기
MASM PWB 사용하기 1. MASM을 설치하면 C:\MASM611 디렉터리가 생성된 것이 보입니다. 그러면 C:\>cd masm611 하여 해당 디렉터리로 들어갑니다. 2. 여러 디렉터리가 보이는데요 그 중에 binr 디렉터리로 들어갑니다. 3. 여러 파일들 중 pwb가 보입니다. 이것이 우리가 사용하게 될 IDE입니다. 4. 글자가 깨져서 보기 불편합니다. 다시 프로그램을 종료하고 명령줄로 돌아갑니다. 5. C:\MASM611\BINR>chcp 437하여 영어 모드로 전환합니다. 6. 이제 메뉴가 깔끔하게 보입니다. 더보기
MASM 설치하기 (MS-DOS 버전) 저는 편의상 VMWare에 MS-DOS를 설치한 환경에서 진행합니다. VMWare에 MS-DOS 설치하는 방법과 플로피디스크 이미지 삽입 방법 대해서는 VMWare로 Windows 3.1 설치하기 - 3. MS-DOS 설치(http://tapito.tistory.com/253) 편을 참조하세요. 먼저 아래 첨부 파일을 다운로드 받으세요. MASM 6.11 설치파일입니다. 1. Disk 1을 A: 드라이브에 넣고 A:\>setup을 입력하면 위와 같은 화면이 뜹니다. MASM 6.11 설치프로그램에 오신 것을 환영합니다. 여기 파일들은 압축되어 있고, 프로그램을 사용하려면 이 프로그램으로 압축을 풀어야 실행 가능합니다. 끝내려면 Ctrl+C, 계속하려면 Enter를 누르세여... 이런 의미겠지요. Ente.. 더보기
MS-DOS API로 배우는 어셈블리어 윈도우에 Windows API가 있다면, MS-DOS에는 MS-DOS API가 있습니다. 차이가 있다면 WinAPI는 C언어로 된 반면, MS-DOS API는 어셈블리어를 사용한다는 차이가 있겠지요. WinAPI에서는 함수를 호출하는 방식으로 API를 사용하지만, MS-DOS API는 레지스터에 특정 값을 넣고, 인터럽트를 발생시키는 방식으로 API를 사용합니다. MS-DOS API의 인터럽트 인터럽트 벡터설명버전비고 20h 프로그램 끝내기 1.0 이상 도스 커널에 추가됨 21h 주요 도스 API 1.0 이상 도스 커널에 추가됨 22h 프로그램 끝내기 주소 1.0 이상 프로그램 호출시 주소 반환 23h Control-C 핸들러 주소 1.0 이상 기본 핸들러는 도스 셸에 있음 (일반적으로 COMMAND.C.. 더보기