배열
배열은 동일한 타입의 데이터 묶을을 의미한다.
배열을 구성하는 각 값을 배열 요소(element)라고 하고
배열의 위치를 가리키는 숫자를 인덱스(index)라고 한다.
어느 프로그래밍이나 존재한다.
어셈블리어에는 배열을 선언하기 쉽다. 변수를 선언할 때, 나열하면 그것이 배열이된다. 또는 times 키워드를 사용해 반복해서 만들어 줄 수도 있다.
a는 1 byte씩 5개를 생성해서 총 5 byte의 메모리를 사용한다. b는 word 이므로 2 byte씩 5개, 총 10 byte를 사용하여 메모리에 할당하게된다.
실제로 이 값들이 제대로 동작하는지 프로그램을 실행해 확인해보자.
a를 보게되면 1, 2, 3, 4, 5까지 총 5 byte가 잘 들어간 모습을 볼 수 있다. 그리고 b는 01 씩 잘 들어간 모습이다.
여기서 의문이 들 수 있다. b는 왜 10 씩 보여지는가?? 그 이유는 인텔 등 cpu에서 리틀 엔디안을 사용하고 있기 때문에 메모리에 저장할 때, 그 값을 거꾸로 해서 할당하기 때문이다.
우리가 보기에는 리틀 엔디안 보다는 순서대로 할당하는 빅 엔디안이 더 좋아보이는데 왜 그러는 것일까?
이것 역시 이유가 여러가지가 있지만 장단점이 서로 존재한다.
빅 엔디안은 값을 비교하기 용이하고 리틀 엔디안은 값을 추출하기 좋다.
그런데 a의 뒷 부분을 보면 b의 일부분이 보이는 모습을 볼 수 있다.
그 이유는 메모리의 주소는 바구니끼리 이어져있기 때문이다. 여길보고 나는 바구니 라는 개념은 그냥 인간이 만들어낸 허상이 아닐까? 라는 생각이든다. 내가 만약 a라는 바구니에서 주소를 한칸만 더 해도 b랑 동일하게 되는거니 사실 바구니의 영역이 급격히 얇아진다.
주소
만약 a를 rax에 그대로 집어넣으면 그 값은 몇이 될까? 한번 확인해보자.
403044가 됐고 403044는 a의 주소, 즉 첫 번째 요소의 주소를 의미한다고 SASM - 2 포스팅에서 다뤘다.
그러면 a의 두번째 요소는 어떻게 접근 할 수 있을까??
바로 주소에 1 byte를 더해주는 것이다. 즉 두 번째 요소는 403045 위치에 있는 것이다. 이 개념 역시 매우 중요하다.
배열, 주소 연습문제
a,b 모든 배열의 요소를 출력하시오.
여기서 보면 b를 출력하는데 있어 ecx * 2를 해줬다. 그 이유는 b는 word이기 때문에 2 byte씩 끊어서 분석을 해야한다. 만약 ecx * 2 가 아닌 ecx라고 한다면 1, 100, 1, 100, 1 이라는 값이 추출될 것이다.
왜냐하면 첫 번째 b의 주소에서 2 byte 만큼 값을 읽어와 0x01 0x00 이것을 리틀 엔디안으로 인해 다시 거꾸로 읽어 출력한다. 그러면 1이라는 값이 출력이 될것이다. 그리고 b + ecx를 하면 b의 주소에서 1 byte 만큼 더해 2 byte를 읽는다. 그렇게 된다면 0x00 0x01이고 이를 리틀 엔디안으로 인해 거꾸로 읽으면 100 이 되기 때문에 우리가 생각한 값이 아닌 아예 새로운 값이 출력하게된다. C++에서는 내가 선언한 변수의 데이터 크기를 계산해 알아서 파싱해주지만 어셈블리어는 그렇지 않는다.
함수
함수는 특정한 기능 단위로 나누어서 자신이 그 기능을 원할 때 호출하여 사용하는 미리 만들어진 도구라고 생각한다. 물론 어셈블리에서는 함수라고 부르기 보단 프로시저(procedure), 또는 서브루틴(subroutine)이라고 한다. 사용 방법은 jump 하는 것과 비슷한데 call [함수명]으로 호출한다.
만약 내가 두 개의 숫자중 큰 숫자를 반환하는 함수를 작성한다고 하자. 그러면 두 개의 입력 값은 어떻게 받아 올 수 있으며 반환은 어떻게 할 수 있을까??
이런 식으로 작성을 해도 가능은 하다. 하지만 만약 인자가 엄청 많아진다면?? 아니면 eax나 ebx에 중요한 값이 들어있었다고 한다면? 어떻게 할까? 매번 수많은 값들을 레지스터나 변수에 저장할 수 없는 노릇이다.
정답은 바로 스택(stack)이다. 스택 메모리는 함수가 사용하는 일종의 메모장이다. 매개변수 전달이나 함수가 호출이 된 후 돌아갈 주소를 관리하는 곳이다.
스택(Stack)
스택 메모리와 스택 프레임에 대해 알아보자.
레지스터는 다양한 용도로 사용된다.
a, b, c, d같은 범용 레지스터도 있지만
- ip(Instruction Pointer) : 다음 수행 명령어의 위치를 가짐
- sp(Stack Pointer) : 현재 스택의 top 위치를 나타냄. 일종의 cursor
- bp(Base Pointer) : 스택의 상대 주소 계산용
등이 있다.
SASM 에서 push 명령어와 pop 명령어를 사용하면서 rip, rsp, rbp 의 값들의 변화와 sp 주소의 메모리를 계속 확인해보면 정말 좋을 것이다.
'C++ > 기초' 카테고리의 다른 글
[C++] 데이터 가지고 놀기 - 2 (데이터 연산, const) (0) | 2023.11.23 |
---|---|
[C++] 데이터 가지고 놀기 - 1 (정수, 불리언, 부동소수점, 문자열) (1) | 2023.11.22 |
[Assemble] SASM - 4 (0) | 2023.11.21 |
[Assemble] SASM - 3 (1) | 2023.11.21 |
[Assemble] SASM - 2 (0) | 2023.11.21 |