%include "io64.inc"
section .text
global main
main:
;write your code here
PRINT_STRING msg1
NEWLINE
PRINT_STRING msg2
NEWLINE
PRINT_STRING msg3
xor rax, rax
ret
section .data
msg1 db 'haha ',0x00
msg2 db 'hellow !',0x00
msg3 db "mnsg3 ok",0x00
입력받기
- SASM에서는 아래 두함수로 받을수 있음
- GET_DEC para1, para2 입력된 문자열 10진수로 인식
para1 입력할 바이트 수 para2 입력받을 곳 레지스터나 메모리주소
- GET_HEX para1, para2 입력된 문자열 16진수로 인식
para1 입력할 바이트 수 para2 입력받을 곳 레지스터나 메모리주소
%include "io64.inc"
section .text
global main
main:
;write your code here
GET_DEC 1,al ;1바이트 입력
GET_DEC 2,a ;2바이트 입력
PRINT_DEC 1,al
NEWLINE
PRINT_DEC 2,a
xor rax, rax
ret
section .bss
a resw 1 ;2바이트 초기화되지않은 변수 a1개 선언
덧셈연산
- ADD para1, para2(para1 = para 1 + para2)
para 1 : 레지스터나 메모리에있는값
para2 : 레지스터, 메모리, 값
*para1,2둘다 메모리인 경우는 안됨
%include "io64.inc"
section .text
global main
main:
;write your code here
mov ax,1 ;2바이트 레지스터에 1대입
mov bx,3 ;2바이트레지스터 bx에 3대입
add ax, bx
PRINT_DEC 2,ax
NEWLINE
mov [a], word 7 ;2바이트 변수 a에 7대입
add ax, [a]
PRINT_DEC 2,ax
NEWLINE
mov bx, 2
add [a], bx
PRINT_DEC 2,a
NEWLINE
mov [b], byte 2
;add [a], [b] <= error!
xor rax, rax
ret
section .bss
a resw 1
b resw 1
뺄셈연산
- SUB para1, para2(para1 = para1 - para2)
para1 : 레지스터 나 메모리 값
para2 : 레지스터, 메모리, 값
%include "io64.inc"
section .text
global main
main:
;write your code here
mov ax,1
mov bx,3
sub ax, bx
PRINT_DEC 2, ax
NEWLINE
mov [a], word 7
sub ax, [a]
PRINT_DEC 2,ax
NEWLINE
mov bx,2
sub [a],bx
PRINT_DEC 2,a
NEWLINE
mov [b], byte 2
PRINT_DEC 2,b
;sub [a], [b] <= 에러
xor rax, rax
ret
section .bss
a resw 1
b resw 1
1바이트 곱샘연산
- MUL para(1바이트)
* para가 1바이트일때 AX = AL * para
* para는 레지스터만 허용
*곱되는값은 무조건 AL레지스터에
*결과는 AX레지스터에 반환
아래 코드에서 ax레지스터를 0으로 초기화안하면 ah 레지스터값에 따라 영향받기 때문
%include "io64.inc"
section .text
global main
main:
;write your code here
PRINT_DEC 2,ax
NEWLINE
;2*3
mov ax,0
mov al, 2
mov bl, 3
mul bx
PRINT_DEC 1,ax
NEWLINE
xor rax, rax
ret
1바이트 나누기 연산
- DIV para(1바이트)
* para가 1바이트일때 : AX / para : AL(몫), AH(나머지)
* 나눠지는값은 AX에
* 연산결과는 AL, AH로 리턴됨
%include "io64.inc"
section .text
global main
main:
;write your code here
; 7(AX) / 2 = 3(AL, 몫), 1(AH, 나머지)
mov ax, 7
mov bl, 2
div bl
mov bl, ah
PRINT_DEC 1,al
NEWLINE
PRINT_DEC 1,bl
NEWLINE
xor rax, rax
ret
실행파일만들고 콘솔에서 실행해보기
코드작성 -> file에서 .exe 로 저장하기 -> 콘솔로 실행
%include "io64.inc"
section .text
global main
main:
;write your code here
PRINT_STRING msg1
NEWLINE
mov ax,3
PRINT_DEC 2,ax
NEWLINE
xor rax, rax
ret
section .data
msg1 db "hello",0x00
사칙연산 계산기 만들기
- 2개의 변수를 1바이트 단위로 받아 메모리에 저장
- 사칙연산 한 값을 1바이트 단위 메모리에 각각 저장
- 나누기 결과는 몫과 나머지를 나누어 저장
- 곱의 경우 결과를 2바이트 변수로 선언하고 사용
- 이후 결과 모두 출력
%include "io64.inc"
section .text
global main
main:
;write your code here
;input
PRINT_STRING msg1
GET_DEC 1,mya
PRINT_DEC 1,mya
NEWLINE
PRINT_STRING msg1
GET_DEC 1,myb
PRINT_DEC 1,myb
NEWLINE
;calc
;+
mov al, [mya]
mov bl, [myb]
add al, bl
mov [a], al
;-
mov al, [mya]
mov bl, [myb]
sub al, bl
mov [b], al
;*
mov al, [mya]
mov bl, [myb]
mul bl
mov [c], ax
;/
mov ax,0
mov al,[mya]
mov bl,[myb]
div bl;
mov [d],al
mov [e],ah
;output
PRINT_STRING msg2
PRINT_DEC 1,a
NEWLINE
PRINT_STRING msg3
PRINT_DEC 1,b
NEWLINE
PRINT_STRING msg4
PRINT_DEC 2,c
NEWLINE
PRINT_STRING msg5
PRINT_DEC 1,d
NEWLINE
PRINT_STRING msg6
PRINT_DEC 1,e
NEWLINE
xor rax, rax
ret
section .data
msg1 db 'input data:',0x00
msg2 db '+:',0x00
msg3 db '-:',0x00
msg4 db '*:',0x00
msg5 db '/(q):',0x00
msg6 db '/(r):',0x00
section .bss
mya resb 1; input 1
myb resb 1; input 2
a resb 1 ; +
b resb 1 ; -
c resw 1 ; *
d resb 1 ; /(몫)
e resb 1 ; /(나머지)
%include "io64.inc"
section .text
global main
main:
;write your code here
mov eax, 0x1234 ;A레지스터 32bit 크기에 0x1234저장
mov ax, 0x1234 ;A레지스터 16bit 크기에 0x1234 저장
mov ax, bx ;bx의 값을 ax로 복사
mov ax,ebx ;[에러발생] ebx(32bit)값을 ax(16bit)에 저장시
xor rax, rax도
ret
어셈블리 메모리
- 메모리 사용 필요한것 : 메모리 크기, 메모리 위치
- 개발자는 메모리 크기 결정은 가능하나 주소는 모르므로 심벌(변수)로 설정하여 사용함.
아래의 경우
변수 명 : a
크기 : 2바이트
시작 주소 : 1
저장 값 : 0x1234
리틀엔디언 빅엔디언
- 메모리에 값(바이트) 저장하는 순서
- 위에서 0x1234가 1에 0x34, 2에 0x12가 들어가는것은 리틀엔디언방식
어셈블리 변수선언 (초기화 x)
- 초기화 하지 않은 변수는 .bss 블록에 언해야함
section .bss
변수명 크기지시자 개수
크기지시자
resb 1바이트 byte?
resw 2바이트 word?
resd 4바이트 double word?
resq 8바이트 qaurd word?
어셈블리 변수선언 (초기화 o)
- 초기값이 있는 경우 section .data 블록에서 선언함
변수명 크기지시자 초기값
크기지시자
db 1바이트 바이트
dw 2바이트 워드
dd 4바이트 더블워드?
dq 8바이트 쿼드워드?
메모리 이용하기,
- mov : 메모리에 데이터 보내기
ex) 변수 a에 저장된 값을 ax 레지스터로 가져오라
-> mov ax, [a]
변수명 = 주소, [변수명] = 주소에 있는값
* []는 c언어의 포인터 느낌으로 생각하면 될듯 []가 없는 변수는 주소 []가 있는 변수는 가리키는 곳
(주의) 어셈블리에서 변수 선언시 크기 지정해줘도 데이터는 크기를 명시해야함.
레지스터와 메모리 값 출력하기
- 레지스터, 메모리에 있는 값을 CPU 어셈블리만으로 출력은 힘듬. OS에 포함되어있기 때문.
1. 초기값 있는 메모리 변수 4개 선언 크기는 1,2,4,8바이트로 값은 16진수로 초기화
2. 초기값없는 메모리 변수 1, 2,4,8바이트 1개씩 선언하고 앞에서 선언한 값을 아래 선언한 변수로 이동
3. 변수 8개 모두 16진수로 출력
%include "io64.inc"
section .text
global main
main:
;write your code here
mov al,[a] ;1바이트 크기 변수 a를 1바이트 레지스터 al에 저장
mov [mya],al ;1바이트 레지스터 al값을 mya에 저장
mov ax,[b] ;2바이트 크기 변수 b를 2바이트 레지스터 ax에 저장
mov [myb],ax ;2바이트 레지스터 ax값을 myb에 저장
mov eax,[c] ;4바이트 크기 변수 c를 4바이트 레지스터 eax에 저장
mov [myc],eax
mov rax,[d]
mov [myd],rax
PRINT_HEX 1,a ;1바이트 단위로 변수 a값 16진수로 출력
NEWLINE
PRINT_HEX 2,b ;2바이트 단위로 변수 b값 16진수로 출력
NEWLINE
PRINT_HEX 4,c ;4바이트 단위로 변수 c값 16진수로 출력
NEWLINE
PRINT_HEX 8,d ;8바이트 단위로 변수 d값 16진수로 출력
NEWLINE
PRINT_HEX 1,mya
NEWLINE
PRINT_HEX 2,myb
NEWLINE
PRINT_HEX 4,myc
NEWLINE
PRINT_HEX 8,myd
xor rax, rax
ret
section .data
a db 0x12 ;1바이트 변수 0x12
b dw 0x1234 ;2바이트 변수 0x1234
c dd 0x12345678 ;4바이트 변수 c
d dq 0x1234567812345678 ;8바이트 변수 d
section .bss
mya resb 1 ;1바이트 초기화안된변수 선언
myb resw 1 ;2바이트 초기화안된변수 myb선언
myc resd 1 ;4바이트 초기화안된변수 myc선언
myd resq 1 ;8바이트 초기화안된변수 myq선