Lab 3 x86_64 finished
Let’s
continue,
Now, we’ll change our code to loop until 30. To make things easier,
I’ll modify my code to be able to use %r15 instead increasing %r8
as we’ll have a divide numbers. So you won’t need to start %r8:
_start:
mov $start,%r15 /* loop index */
mov $10,%r9 /* initialize register with line feed */
But now, you’ll need to replace %r8 for %15 (mov %r15,%r8) and
convert into a character adding 48 (add $48,%r8), do this in the
beginning of the loop and remove the inc of %r8 (inc %r8), so the
beginning of your loop will be like:
loop:
mov %r15,%r8 /* replace %r8 with the counter */
add $48,%r8 /* add 48 to turn into a character */
mov %r8,d /* replace d with %r8 value */
mov %r9,l /* replace l with %r9 value */
movq $len,%rdx /* message length */
movq $msg,%rsi /* message location */
movq $1,%rdi /* file descriptor stdout */
movq $1,%rax /* syscall sys_write */
syscall
inc %r15 /* increment index */
As 10-30 needs more space than 1-9, we’ll have to add a third space
in our message to fit the right length ("Loop: \n").
We’ll have two digits, so d will be now d1 (d1 = msg + 6), we’ll
have a d2 (d2 = msg + 7) and l will be in position 8 (l = msg + 8).
As we have two digits, I prefer to put them in a row, so I’ll move
the line feed to %r10 (mov $10,%r10), the first digit will
initialize with an empty space (mov $32,%r8).
Obs.: As you maybe remember, we’re working with ascii number. So 32
is the ascii to an empty space.
Remember that we have to modify the loop too, so the beginning of our
code we’ll be like this:
_start:
mov $start,%r15 /*
loop index */
mov $32,%r8 /*
initialize register with space */
mov $10,%r10 /*
initialize register with line feed */
loop:
mov %r15,%r9 /* replace %r9 with the counter */
add $48,%r9 /* add 48 to turn into a character */
mov %r8,d1 /* replace d1 with %r8 value */
mov %r9,d2 /*
replace d2 with %r9 value */
mov %r10,l /*
replace l with %r10 value */
And our
data like this:
msg: .ascii "Loop:
\n"
len =
. - msg /* message length */
d1 =
msg + 6 /* position of second space */
d2 =
msg + 7 /* position of third space */
l =
msg + 8 /* position of line feed */
Now we can test. We’ll be able to see our same code, but now with
another space in the middle. If you try modify the max to 31 (it will
execute until 0-30, max = 31) you’ll see that it’s not so simple
to print numbers in assembly (I don’t know you, but I already knew
it when I lost some hours in the 0-9 program). The increment will not
add +1 to our digits, but 1 to ascii digits, that’s why you’ll
see some weird characters instead of numbers. To solve this, we’ll
have to divide the counter and take the quotient and remainder to
write the first and second digit respectively.
To divide, we need first to put 0 in the rdx (mov $0,%rdx), then
put the number that we need to divide in the %rax, in this case,
%r15, the counter (mov %r15,%rax) and divide per 10 to have the
two numbers, as we already have this number to the line feed, we
don’t have to use another register (div %r10). The first
number, the quotient, will be in rax and the second, the remainder,
in rdx. We have to put these number in the registers (mov
%rax,%r8 and mov %rdx,%r9) and add 48 to have the string (add
$48,%r8 and add $48,%r9).
Obs.: Note that you don’t need to initialize %r8 anymore, as you’ll
receive the quotient before being printed (mov $32,%r8).
The last thing, before the full code, is to remove the “0” before
the numbers 0-9. To do that, I’ll compare 48 with %r8 before
turning it in a character number (cmp $48,%r8), if it’s zero,
I’ll go to a label, named space (je space), to replace it for
a space (mov $32,%r8). Either if it is or it isn’t zero, I’ll
continue to another label (jmp continue) to continue the code and
write the result in the screen.
You’ll be able to see the full code in
https://drive.google.com/file/d/1Z3Z0lCj13nJvGfV8rMa84VKgR31ay-ON/view?usp=sharing
. Next post we’ll do the same thing in a aarch64 architecture.
Comentários
Postar um comentário