Lab 3 (the very beginning)

Hello again,

This time I started to program in assembly. I’ve have heard before that programming in assembly is a thing to crazy guys, but everyone that start to program is a little crazy, isn’t it? So let’s begin and see how crazy we can be. To start, my professor has give me some “hello world” code, some material to study and an example of loop in x86_64 assembly. As I never had a Linux class and everything that I learn of Linux was googling my needs (I’m a exchange student, doing the program for only a semester), I follow the tip of my professor to use vi program, because it’s already installed in every Linux machine and it would give me less headache. So, I used “vi loop.s” command and paste the loop example:

.text
.globl _start

start = 0 /* starting value for the loop index; note that this is a symbol (constant), not a variable */
max = 10 /* loop exits when the index hits this number (loop condition is i<max) */

_start:
mov $start,%r15 /* loop index */

loop:
/* ... body of the loop ... do something useful here ... */

inc %r15 /* increment index */
cmp $max,%r15 /* see if we're done */
jne loop /* loop if we're not */

mov $0,%rdi /* exit status */
mov $60,%rax /* syscall sys_exit */
syscall

Obs.: The “vi file.extension” open the file in vi program, if the file does not exist, it creates one.
Obs.2: You have to type i to enter insert mode in vi, so you can paste the code.
Obs.3: Paste the code with ctrl+shift+v, not ctrl+v (same to copy code, use shift as well) in the terminal (if you can use a text editor separately from the terminal, luck of you, I couldn’t, so use the one you wish).
Obs.4: To save, press Esc to exit insert mode and then type :wq. When you press enter this will exit and save what you typed.
Obs.5: As I said, this is a x86_64 architecture code, so be sure that this is the architecture of your machine, if it’s not, I’ll do a aarch64 code too, but pay attention in this explanation because I won’t repeat some things. I won’t separate x86_64 and aarch64 in more visible sections, so you’ll not jump to aarch64 and lost knowledge (no, it’s not because I’m lazy).
Obs.6: This was a group activity, my group wrote a beautiful code that a vaguely understand, but I tried to save it and take a look in home. Well, I tried. I tried and failed. I couldn’t find it, so my code will be uglier than my group one.

So, with the base code, we’ll start to write the modifications, right? Wrong. First we have to test if something goes wrong in “my” code that does nothing (it’s better do nothing than give us a error message, right?). So, to be faster, I’ve wrote a Makefile (vi Makefile) as follow:

loop: loop.s
as -g -o loop.o loop.s
ld -o loop loop.o

Obs.7: Use tab, not space, it could give you some errors.

After write this, I had only to use make command and then, execute (./loop). And (after I fixed some mistakes that I have done, as tried to compile as x86, not x86_64) nothing successfully happens, =D! Now what? Let’s modify our code to write something, but what? A loop of course, a loop that goes from 0 to 9. How? I looked in my professor Hello world example and saw how to add data on the code. After the code I wrote in loop.s I added this:

.section .rodata

msg: .ascii "Hello, world!\n"
len = . - msg

Where I’m creating a variable (or something like that), it’s a string (ascii format) and saying that len will take the length of it. With my message, I had to show it, so I copy another part of the code that shows the message to the user and replace the comment in the loop (/* ... body of the loop ... do something useful here ... */):

movq $len,%rdx /* message length */
movq $msg,%rsi /* message location */
movq $1,%rdi /* file descriptor stdout */
movq $1,%rax /* syscall sys_write */
syscall

I modified the msg to “Loop\n” instead "Hello, world!\n", used make command, then ./loop command and I get ten “Loop” messages in response. Now, how to show number? This part take me some hours of research as I didn’t understand the professor tips very well. First, as you will modify your data, change the .rodata (read-only data) section name to .data. Then, change message to “Loop: \n” (there is two spaces, the second space will be replaced by the number). Now, as you’ve created a variable len, you’ll create another two, I’ll call it d (digit) and l (line feed or \n). d will receive the pointer of the second space (d = msg + 6) and l the pointer of \n (l = msg + 7), \n counts as one character. Our section will be like this:

.section .data

msg: .ascii "Loop: \n"
len = . - msg /* message length */
d = msg + 6 /* position of second space */
l = msg + 7 /* position of line feed */

At _start, I initialize registers to replace d and l (the values can’t directly replace d and l, they have to be in registers first), %r8 I initialize with $48 (mov $48,%r8), remember that 48 is 0 in ascii, and %r9 I initialize with $10 (mov $10,%r9), 10 is the line feed or \n in ascii:

_start:
mov $start,%r15 /* loop index */
mov $48,%r8 /* initialize register with 0 */
mov $10,%r9 /* initialize register with line feed */

Now I only had to replace the d value with the value of %r8 (mov %r8,d) and l with %r9 (mov %r9,l) before the code that shows the message:

mov %r8,d /* replace d with %r8 value */
mov %r9,l /* replace l with %r9 value */

So, the message would show “Loop: 0”, now we just have to increment the number after each output (inc %r8). The whole code will seem like this:

.text
.globl _start

start = 0 /* starting value for the loop index; note that this is a symbol (constant), not a variable */
max = 10 /* loop exits when the index hits this number (loop condition is i<max) */

_start:
mov $start,%r15 /* loop index */
mov $48,%r8 /* initialize register with 0 */
mov $10,%r9 /* initialize register with line feed */

loop:
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 %r8 /* increment number */
inc %r15 /* increment index */
cmp $max,%r15 /* see if we're done */
jne loop /* loop if we're not */

mov $0,%rdi /* exit status */
mov $60,%rax /* syscall sys_exit */
syscall

.section .data

msg: .ascii "Loop: \n"
len = . - msg /* message length */
d = msg + 6 /* position of second space */
l = msg + 7 /* position of line feed */

Obs.8: We can’t only change the msg + 6 position, so we’ll still have the \n? No, when we modify this position it deletes everything after it, so we have to modify the msg + 7 position to have the \n again.

Obs.9: Can’t we have only “Loop: ”? No, because the length will be less than it needs, so if you try to modify msg + 6 you’ll access invalid memory and the program will probably not execute or broke (I haven’t tested, but feel free to try if you want, =D).

Obs.10: Blogger erase all my tabs, but I'll post my codes with links when I finish.


Have we finish? Haha. We’re not even in the half. Now our loop has to go until 30. But as this post seems to be very big, I’ll finish for now and post the rest later.

Comentários

Postagens mais visitadas