본문 바로가기

무언가 만들기 위한 지식/SPARC Assembler

SPARC Assembler Argument(about argc, argv)_인자에 대해서

아, 한동안 시험과 기타 일정때문에 블로깅을 못하고 Assembler에 대해, 다시 시작하게되었다.
뭐 Sparc Assembler가 그닥 사용할 일이 없기 때문에 앞으로 2~3개 정도의 포스팅이 더 올라가고 앞으로는 올릴 일이 없을 것으로 예상된다.
필자의 학기중 시험도 이미 모두 끝난 상태이고, 아마 취업이나 기타면에서도 사용할일은 없을 듯하나, (Sparc계열이라..)
그래도 끝까지 마무리 해볼려고 한다^_^

Assembler도 C에서 사용되는 모든 기능이 구현이 가능하다.(뭐 C보다 하층 언어니 당연하지만서도...)
이번에는 그중에서 실행명령어의 인자들을 받아들여 사용하는 것에 대해 직접해보도록하자.

물론 기본적으로 argc와 argv에 대한 이해가 필수적으로 필요하다.
console창에서 실행 명령어를 사용할때 보통,


위와 같이 명령어 옆에 인자들을 넣어주게 된다.
위의 경우 첫번째는 인자로 shinlucky와 shin444가 주어진 것이고,
두번째는 인자로 shinlucky, -o, shin444가 주어진 것이다.

이 명령어들을 가져와 코드상에서 string들을 사용하게 된다.
C에서 자주 접하게 되는 코드는 다음과 같다.


위의 C언어 예제는 네트워크의 기본적으로 사용되는 코드를 좀 긁어왔다.
보시다시피 main안에 인자로 int argc와 char *argv[]로 선언이 되었고, 코드내에서는 argc는 int형으로 argv는 string처럼 사용되는 것을 확인할 수 있다.

argcargument Count의 약자이다. 즉 인자의 개수를 말한다. 사진을 첨부한 예제에서 보면
[a.out shinlucky shin444]
에서 인자는 3개이다. 즉 int argc에는 3의 값이 들어있게 된다. [명령어 자체를 포함한 인자이다.]
소스 예제에서 보면 초반에 명령어 사용법을 지키지 않으면 사용법을 출력하고, 프로그램을 종료하는 모습을 볼수 있다.(7~11 Line)

argvargument Vector의 약자이다. Type을 보면 이중배열로 되어 있다. 한마디로 말하면 String(Char *)가 배열로 되어 있다. 즉 argv[0], argv[1], argv[2]........에는 각 string(Char *)의 값들이 저장되어 있다. 접근도 argv[i]식으로 접근해서 그대로 가져다 사용하면 된다. (하지만 const라서 따로 가져다 사용만 가능하다. 고정문자열이랄까나...)

즉 보통 패턴은 argc로 명령어 사용시 오류를 체크해주고 argv로 인자를 가져다 쓰는 것이다.
뭐 사실 이 Assembler 포스팅을 보시는 분들정도면, 이정도는 다 알고 있으리라 믿는다.
(다 아시는 것 뻘짓하는거 아닌가 싶음 ㅜ.ㅠ)

필자는 포스팅을 하면서 사전과 위키피디아를 찾아보는 습관이 생겼는데,
Argument의 뜻에대해 찾아보았다.
평소 논증, 토론이라고 생각하고 있었다. (물론 컴퓨터 용어란 것도 알고 있었다.)
혹시나해서 쓰윽 찾아보니,


6번에 컴퓨터 용어로 인수, 독립 변수라고 번역이 되어 있다.
이 의미를 생각한다면 인자, 무엇인지 대충 이해가 빨리 가리라 생각한다.

C에서는 아주 빈번히 사용되는데, 이를 이제 Assembler에서 사용해 보자.!
필자도 처음에는 뭘로 가능하지라는 생각을 했지만, 지금까지 Sparc Assembler의 Subroutine부분의 이해가 되었다면 이것도 간단한 원리이다.

Main도 하나의 함수처럼 Stack에 쌓인 형세이고, 이는 즉 그 전에도 shell이나 이런저런 기반 stack이 쌓여있다는 것이다.
Sparc Assembler에서 함수의 매개변수(parameter)는 %i0~%i5로 이루어진다. 이처럼 Main에서도 이전에서 %i Register를 통해 무언가 값을 전달 받게된다.

결론을 말하자면 결국 argc와 argv는 %i Register를 통하여 전달받는다는 것이다.
argc의 경우 word(4byte)이기 때문에 그냥 사용하면 된다.
하지만, 생각해 볼것은 argv의 경우이다.

더블 포인터이기 때문에 포인터 개념을 확실히 알고 잘사용해야 한다.
간단히 생각하려면 String들을 가리키고 있는 포인터라고 보면 된다.

정리하자면
argc : %i0
argv : %i1

에 존재한다.
단 argv의 경우 String이 존재하는 공간을 가리키는 주소 값 이 들어가 있다.
그리고 %i1의 값을 4씩 증가하면서(주소가 4byte이므로) 다음 argv값으로 접근 가능하다.
(마치 argv[0], argv[1]로 가는것처럼)

그럼 직접 예제 코드를 살펴보도록 하자 ^_^



위 코드는 두개의 정수를 인자로 입력받아,
두수의 합을 출력하는 코드이다.
큰 맥락은 인자로 두개의 String을 받은후, 이를 atoi 함수를 사용하여 정수로 바꾼후 연산을 수행하는 것이다.
9~11 Line, 27~31 Line에서 지정한 인자를 사용하지 않은 경우 에러출력후 바로 종료하는 루틴을 만들어 주었다.
간단히 %i0 레지스터의 값이 3이 아니면 종료하는 방식이다.

이해하기 까다로운 부분은 argv이다.
코드상에서는 12, 13, 14 Line에서 12 Line에서 다음 argv를 가리키도록 하고 (ex: argv[1])
14에서 argv의 처음 주소를 %o0에 가져다 놓는다.
%o0에 넣는 이유는 atoi함수를 콜하기 위함이다.

결국 두번째 문자열의 첫번째 주소값을 가져왔다고 생각하면 된다.
만약 %o0에 문자열의 첫번째 주소값이 있다고 하였을 때, %s로 출력을 해보면 잘 출력된다.
C언어의 포인터 개념이 좀 필요하다 -.,-

결국 add %i1, 4, %i1로 다음 argv로 접근한 것이고, 각 atoi를 call하여 String을 int로 바꾼후 연산하여 출력한 것이다.
결과값은 다음과 같다.


<인자를 주지 않았을 경우(인자가 3개가 아닐 때), 올바른 사용법 출력후 종료>


<인자 두개를 올바르게 주었을 경우 두개의 합이 출력된다.>


※ Assembler의 atoi함수는 %o0에 String의 첫 주소를 넣어주면 interger로 변환시켜 결과 값을 다시 %o0에 돌려준다. 같은 함수로 atof등이 있다. 꽤 유용하고 편하다. 사용하다보면 최악의 경우 data영역에 문자열로 저장해놓고 변환해서 쓰게되는 경우도 있다.
(물론 상당히 무식한 방법, align이 잘 안될경우 이렇게도 해본적이 있음 ㅋ)