간단한 어셈블리(nasm)어 질문 입니다..
1 section .data ;섹션 .data 를 선언한다.(여기부터 2 ; .data 섹션이다.) 3 4 msg db "Hello, world!",0xa ;출력할 사랑스런(!) 스트링이다. 5 len equ $ - msg ;친애하는(!) 문자열의 길이 6 7 section .text ;여기부터 .text 섹션이다. 코드있음 8 9 ;ELF 링커나 로더에게 프로그램의 엔트리 포인트를 알려주어야 10 global _start ;한다. 로더 혹은 링커는 일반적으로 엔트리 포인트가 _start 11 ;라고 가정하고 있다. 이 디폴트 설정을 바꿀려면, 12 ;ld -e foo 를 사용하라. 13 ;시작 지점 정하는거 14 15 _start: 16 17 ;write(int fd, const void *buf, size_t count) ==> 18 ;4번시스템콜인 write(1,msg,len); 함수를 쓴거랑 같다.. 19 ;stdout 에 우리의 사랑스런 문자열을 출력하자. 20 21 mov eax,4 ;eax 레지스터에 호출할 커널 시스템 콜의 번호를 넣어 준다. 22 ;이 경우에는 4번(sys_write) 이다. 23 24 mov ebx,1 ;시스템 콜 4번은 첫번째 인수로 파일의 핸들(디스크립터)을 25 ;취한다. 26 27 mov ecx,msg ;시스템 콜 4번은 두번째 인수로 출력할 메세지가 담긴 메모리 28 ;주소를 취한다. 즉, 출력할 메세지로의 포인터를 취한다. 29 30 mov edx,len ;시스템 콜 4번(sys_write)은 세번째 인수로 출력할 메세지의 31 ;길이를 취한다. 32 33 int 0x80 ;커널을 호출한다. 34 35 ;출력이 끝났으면, exit 를 호출한다. 36 37 mov ebx,0 ;exit 코드로 0을 준다. (c 코드로는 exit(0);) 38 39 mov eax,1 ;시스템 콜 1번 (sys_exit) 40 41 int 0x80 ;커널을 호출한다.
c로 하면..(아는거만..)
char *msg="hello, world!"; int len=....;//(....;;) main() { write(1,msg,len); exit(0); }
1..section .data
section .text
이런식으로 나눠서 하던데요,,, 어떤 종류의 section 들이 있죠?
그리고 각 값으로 무었을 넣어야 하나요?
2. register
eax,ebx,ecx,edx가 각각 ax bx cx dx아닌가요? (16비트인가 32비트 부터 e를 붙인다는걸로 알고 있습니다)
시스템 플밍 책에 적혀 있기에.
ax:accumulator (산술 논리 연산에 사용)
bx:base (address) register (베이스 주소 지정??)
cx:counter register (세는 역활 하는거 같습니다)
dx:보조 accumulator
이라고 적혀 있는데요.. 사실 nasm이나 masm으로 하니까
eax(콜할 함수 번호),ebx(인자1),ecx(인자2),edx(인자3...),
라는것도 시스템 콜하는데에 쓰일 뿐인데..(C함수처럼..)
왜 저런식으로 설명해 놓은건가요?? 어셈책 다 그런식으로 해놨던데..
무슨 연관성이?
3 변수(이름?) 선언..
section .data 부에..(여긴 선언(?) 할 데이터들을 적어 놓는 곳이죠???)
msg db "Hello, world!",0xa
라고 적혀 잇는데 대충 해석하면
msg란 이름(?) 을 db(?)형으로 잡은다음(아마도 크기) "Hello, world!"란걸 넣어라..는것 같아요..
db가 뭔가요; 그리고 edu는?? $표시는??
아! 그리고 마지막에 저 주소값은 뭐죠??
설명해주실때는 C랑 좀 비교하면서 가르켜 주시면 감사하겠습니다.. 제가 그나마 아는 언어가 C 뿐이라서요.
그리고 무슨 nasm튜토리얼 을 어떤분계서 한글화 하신다고 들었는데..(전에 글 보니..) 어떻게 되었는지요..
1. .text섹션에는
1. .text섹션에는 실행할 코드, .data 섹션에는 초기값이 있는 전역 변수, 혹은 스태틱 변수 등이 들어갑니다. 그 밖에는 bss 등에 해당하는 섹션도 있을 수 있습니다.
2. 원래 intel 프로세스가 16 bit 에서 시작했는데 그 떄 사용하던 이름이 ax, bx, cx, dx 등이었는데, 32bit 로 넘어어면서 하위 호환성을 유지하기 위해서 eax, ebx 등으로 바뀌었습니다.
그렇게 적혀 있는 이유는 인텔 아키텍쳐 인스트럭션을 쓰다 보시면, 특정 인스트럭션이 ax, bx, cx, dx 등과 같은 일반 레지스터를 특정한 용도로 사용하는 경우가 있습니다. 그럴 때 사용되는 용도를 적어 놓은 듯 합니다.
ax, bx 같은 일반 레지스터는 필요할 때 임의로 사용할 수 있는 레지스터라, 시스템 콜 할 때 그렇게 사용하자고 리눅스에서 정한 것 뿐입니다. 다른 인스트럭션 사용시는 다른 용도로 사용 될 때도 있습니다.
인용: 2. 원래 intel
오해가 있을까봐 첨언을 달아둡니다.
레지스터-메모리간 빠른 전송을 위해 레지스터를 32비트로 확장했고
32비트 레지스터를 가리키기 위해서 extended ax라 해서 eax라고 이름을 지었습니다.
그렇다고 ax를 사용할 수 없는 것이 아니라 ax(ah, al)을 모두 사용이 가능합니다.
이게 하위 호환성이겠죠.
또한 64비트 시스템에서는 레지스터도 64비트인데 64비트 레지스터를 가리키기 위해서 rax라는 이름을 만든 것으로 알고 있습니다. 물론 eax, ax모두 사용가능합니다.
한 걸음 더 가까이
2. ax, bx, cx, dx의
2. ax, bx, cx, dx의 역할은 16비트 시절의 잔재입니다.
(1) 산술 명령에는 ax를 기본으로 사용하는 것들이 있습니다. mul이나 div 같은 것들은 ax를 생략하고 사용할 수 있는 기능이 있습니다.
mul bx 라고 하면 dx:ax = ax * bx가 됩니다. dx를 32비트 확장용으로 사용한 것 때문에 dx는 보조 accumulator라고 하는 것입니다.
(2) bx는 base 레지스터라고 되어 있는데 배열의 예로 들면 a라는 배열의 i번째 인덱스 값을 얻고 싶다면
mov bx, offset a
mov si, i
mov ax, [si + bx]
이런 식으로 사용합니다. 16비트 시절에는 si나 di 같은 인덱스 레지스터에서 유일하게 레지스터 조합으로 사용할 수 있었던 것이 bx
레지스터였습니다. 그 때문에 bx가 base 레지스터가 불리는 것입니다. (사실 bx를 의도적으로 base 레지스터로 설계한 것이죠)
(3) cx는 x86의 repeat 명령에 사용하는 카운트 레지스터입니다. cx에 원하는 반복횟수를 넣고 rep 같은 반복 명령을 쓰면 뒤에 나오는
명령이 반복 횟수만큼 실행됩니다.
지금 나오는 x86 CPU 들도 윈도우 진입 전 상태인 리얼모드에서는 저 제약사항을 가지고 있습니다. 32비트 명령부터는 저런 제약이 많이
없어졌습니다. 자세한 내용은 인텔의 IA32 관련 pdf 파일들을 참조하시기 바랍니다.
그럼...
전에 본 내용인데 도움이 될 것 같아 올립니다.
// 어셈블리에 관한 내용입니다.
http://kldp.org/node/30171
// 인텔 프로세서 메뉴얼에 관한 내용입니다.
http://kldp.org/node/22184
댓글 달기