학교 인라인 어셈블리 과제

Posted by ho95

또다시 돌아온 과제

다시 과제가 나왔습니다. 이번엔 C언어를 바탕으로 중간중간 어셈블리어를 혼용하여

코드를 작성하는 것입니다. (NASM이아닌 ATT문법)

내용은 똑같습니다. A-Z 출력하기, 한 자리수를 입력받아 그 수만큼 줄바꿈(\n)을 하고 A출력하기

그리고 n1,n2를 입력받아 n1~n2까지의 합을 구하기 입니다.

처음엔 오히려 C언어를 사용할 수 있으니까 좀더 빨리 끝낼 수 있을 줄 알았는데, 해맸습니다 ㅎㅎ..

항상 기초적인 것을 내주시지만 기초가 없어서 어렵습니다.

ASM() 함수

C언어에서 어셈블리어를 혼용해 사용하기 위해서는 asm()함수를 사용합니다.

형식은 asm(“어셈블 명령어”:출력변수:입력변수)입니다.

여기서 입출력 변수란, C언어에서 선언한 변수들을 뜻합니다.

어셈블 명령어는 한개, 또는 복수개가 올 수있습니다.(복수개 사용시 ;을 붙혀 주어야 합니다.)

출력변수 부분은 레지스터에서 C언어 변수로 내보내면 “=r”(변수명)을 해줍니다. (대부분..=r)

입력변수 부분은 C언어 변수에서 레지스터로 값을 불러올시 “r”을, 메모리에서 불러올시 “m”을 사용

하지만 메모리에서 불러오게 되면 속도의 차이가 좀 있습니다.

그리고 불러온 입출력 변수를 어셈블 명령어에서는 “%번호”로 구분합니다.

예를 들어 asm(movb %0, %%bl”::”r”(a))의 경우, 출력 변수 옵션은 없고, 입력 변수에 “r”(a)라고

있습니다. 이 뜻은 호스트 언어의 a변수를 bl이라는 레지스터에 넣는다는 뜻인데, 입력 변수가

하나뿐이라 %0를 써주었습니다. 여러개 있다면 %0부터 시작해서 +1씩 하면 됩니다.

참 호스트 언어의 변수를 레지스터로 불러오거나 그 반대의 경우에 %를 한번더 써주어야합니다.

ATT문법에서 레지스터 앞에 %를 붙힙니다만, 작성되는 코드는 C언어이기 때문에 %를 한번 더

붙혀서 “%레지스터명”로 확실하게 인식 시켜주게 합니다. 그리고, 입력 변수가 1개 이상일시

eax(ah,al)은 사용하지 않는게 좋습니다. 변수에서 레지스터로 값을 불러올시 eax의 값을

보장할 수없습니다.

밑의 실제 코드를 보시면 조금 이해하는데, 도움이 되지 않을까 합니다.

과제1: A~Z까지 출력하기


hw4_1 01

일단 실행 결과입니다. 햇갈렸지만 출력하는 코드가 printf하나만 써주면 되어서 코드 길이는

순수 어셈블리어로 작성 했을 때 보단 많이 짧아졌습니다. 코드는 사진과 같습니다.

코드를 보면 변수의 값을 가져올때 %가 한번더 붙은게 보이시나요?

hw4_1

문자 ‘A’가 저장된 char형 변수 a(1바이트), asm(loop:)로 점프할 위치 만들기

a가 1바이트 char형이기 때문에 어셈블 명령어는 b를 붙혀주어여하고 레지스터는 xH(xL)을 사용.

일단 bl에 ‘A’를 넣어놓고, printf로 a에 있는 ‘A’를 출력 해줍니다.

incb를 통해 bl에 있는 ‘A’=0x65를 1증가시켜 ‘B’=0x66이 되게 합니다.

그리고 movb를 이용하여 a에 1증가된 bl(‘B’)를 새로 넣어줍니다.

그 후, 알파벳이 총 26자이고, A가 65부터 시작하므로 91까지 cmp로 비교를 합니다.

bl이 증가는 하겠지만 그전 까지는 같지 않으므로(cmp가 음수이므로) jne 또는 jl을 사용하여

loop로 점프 후 다시 반복 하는 코드입니다.

과제2: 한자리 수를 입력받아 줄바꿈후 A출력하기


hw4_2 01

실행결과입니다. 제대로 작동하네요. 코드는 아래와 같습니다.

hw4_2

char형 변수 a에 ‘A’를 넣어줍니다. 그리고 한자리 수의 숫자가 들어오기 때문에 char형 변수 b를 선언

scanf로 b에 한자리 수를 받아줍니다.(1바이트이기 때문에 hhd, 아마.. halfhalfdec가 아닐지)

점프를 위한 L1:을 선언 해주고, 입력받은 b의 값을 bl로 옮겨줍니다.

줄바꿈 한번 해주고, bl을 1감소 후, b에 넣어줍니다.(출력이기 때문에 “=r”사용/입력시 “r”)

그 후, 0과 bl의 값을 비교해서 cmp 결과가 양수일시 L1으로 다시 점프하게 됩니다.

그리고 마지막으로 a를 출력후 종료하게 됩니다.

과제3: n1,n2를 입력받아 n1~n2의 합 구하기


hw4_3 01

실행 결과입니다. 잘 나오는군요. 아래는 코드입니다.

hw4_3

n1,n2를 입력받기 위한 int형 변수 a,b이며, c는 n1~n2까지의 합을 저장하기 위한 변수입니다.

scanf로 a,b에 n1,n2를 입력받습니다.

a,b에 입력 받은 값을 각 ecx,edx로 옮깁니다. (int형이기 때문에 movl과 32bit인 ecx사용) ,로 변수2개

점프를 위한 L1:을 지정합니다.

addl을 이용하여 edx(c)에 ecx(a,n1)을 더한 후, ecx(a,n1)을 1증가시킵니다.

cmpl을 사용하여 1증가된 n1과 덧샘의 한계 값인 b(n2)와 비교를 합니다.(입력변수 1개이므로 %0)

n2보다 같거나 작을시(cmp값 음수) L1으로 다시 점프하여 반복 후 movl을 이용하여 edx(c)를

최종적으로 넣어줍니다. printf로 c를 출력하면 끝!

마무리


매번 글을 적지만, 정리해서 깔끔하게 적는게 제일 어려운 것 같습니다.