1

I am pretty new to assembly, and I am struggling quite a bit trying to learn. I have a program written in C, that is supposed to call some routines written in assembly. I also have these routines in C, so I can inspect them and know exactly what they need to do once I write them in assembly.

In particular, I am struggling with this one:

void showNumberP1_C() {
   
   int n = number;
   int i;

   if (n > 999999) n = 999999;
   for (i=0;i<6;i++){
     charac = ' ';
     if (n > 0) {
       charac = n%10;     //residuo
       n = n/10;          //cociente
       charac = charac + '0';
     }
     gotoxyP1_C();
     printchP1_C();
     colScreen--;
   }

}

I have written the following code in assembly to mimic this function:

showNumberP1:
   push rbp
   mov  rbp, rsp
   
   mov eax, DWORD[number]

   cmp eax, 999999 ; if (n > 999999)
   jle endif1
   mov eax, 999999

   endif1:
   mov esi, 0
   
   for:
   cmp esi, 6
   jg fortrue
   jmp endfor
   fortrue:
   mov al, ' '
   cmp eax, 0
   jle endif2
   mov edx, 0
   mov ecx, 10
   div ecx
   mov al, edx
   add al, '0'
   endif2:
   mov BYTE[charac], al
   call gotoxyP1_C
   call printchP1_C
   dec DWORD[colScreen]
   jmp for
   
   endfor:
   mov rsp, rbp
   pop rbp
   ret

The variables number, charac and colScreen are globals defined in the C part of the program.

char charac;
int  colScreen;
int  number;

My problem comes up when I need to use the modulo operator. Since n is an int, I assign a DWORD type register to it (eax in this case); on the other hand, since charac is a char, I assign a BYTE type register to it (al in this case). When I do

mov edx, 0
mov ecx, 10
div ecx

I expect to do eax = n/10, and I expect the remainder to go to edx (my first question would be if I am right on this assumption, as I am struggling to understand div).

But then, I would like to get the value of this remainder to charac, but obviously I cannot do

mov al, edx

Since al is a 1 byte register while edx is a 4 byte register. So I don't know the correct way to handle this situation. I would appreciate getting some help on this particular question, and also any general comments on how to write better assembly code.

Thanks!

phuclv
  • 37,963
  • 15
  • 156
  • 475
AAB07
  • 45
  • 4
  • 1
    Recall that `dl` is the low 8 bits of `al`. So you can simply do `mov al, dl`. But note that `al` is the low 8 bits of `eax`, so moving to `al` will trash your quotient. – fuz Nov 12 '22 at 14:55
  • 2
    @fuz I think you've got a bit of a typo there, with `al`. – Thomas Jager Nov 12 '22 at 15:10
  • 3
    Should have said: “recall that `dl` is the low 8 bits of `edx`.” Thank you for the correction. – fuz Nov 12 '22 at 15:23
  • 1
    [How do I print an integer in Assembly Level Programming without printf from the c library?](https://stackoverflow.com/a/46301894) has a loop like this that stores to memory decrementing a pointer. (And with some points about efficiency; if you want it to be fast, use a multiplicative inverse like a C compiler would, or just a compiler do it and look at the asm.) With the store as part of the loop, I didn't have to worry about trashing the quotient, just store from DL. Also your C is weird, you have these global variables instead of function args? Yuck. – Peter Cordes Nov 13 '22 at 12:48

0 Answers0