Home > Enterprise >  Assembly language program loop, printing a message
Assembly language program loop, printing a message

Time:10-19

so ideally, I want this program to run the total number of characters that are in a msg. So for example "Hey there", there are 10 characters. It'll iterate 10 times. (I assume like C, you have to account for the space)

I hard-coded the values in because I'm having a difficult time figuring out how to have it read the number of characters within this string. I tried my code & it'll run once then wait for me to do something in the terminal. Or it'll seg fault (I've tried to do this about 100 times already, different ways everytime)

What am I doing wrong? I feel like it's something so simple I'm just overlooking! I tried to use the debugger to figure out what I'm doing wrong but I'm new to assembly so I'm a bit confused. So, if you could explain what the "computer" is doing that would help a lot!

For refrence this is my code:

section .text   
    global _start

_start:
   mov  edx, 13  ;;message to write
   mov  ecx, msg     ;message length
   mov  ebx,1       ;file descriptor (stdout)
   mov  eax,4       ;system call number (sys_write)
   int  0x80        ;trigger system call



mov ax, 13

loop_top:
    cmp ax, 13
    je loop_top

section .data
        
    msg  db  'Hello there!' ,0xa;the string of we want to pass
    ;;len  equ  $ - msg         ;length of our string

CodePudding user response:

If you want to find the length of a string you can do the following.

First, make sure your string has an identifier at the end that makes you know that your string has ended, a null terminator is the default in most languages (in C for example).

str db "Hello, world!", 0x00

Then you need to iterate over this string until you reach 0x00. You can do something like:

findStringLength:
    mov cx, 0x00 ; lets keep a count on the character

iterate:    
    mov bx, str ; get the address of the string
    add bx, cx ; add the character count that we kept

    mov al, byte[bx] ; put the iterated character inside al
    cmp al, 0x00 ; check if we reached the end of string
    je endIteration ; end iteration if we did.
 
    ; do something with character in al
    ; ...
    ;

    inc cx ; increase the iterator
    jmp iterate ; loop


endIteration:
    mov ax, cx ; return the length in ax
    ret

This code is a template but you get the idea

CodePudding user response:

Like you said, it's a very simple thing you overlooked. Don't feel bad - I can't tell you how many times I did this.

Here's the problem:

mov ax, 13

loop_top:
    cmp ax, 13
    je loop_top

You set ax to 13, and then you're checking over and over again until it's no longer 13. Since nothing is changing the value of AX, the je loop_top is always taken and you just end up looping forever. And if somehow that branch isn't taken... You see, even though we've declared section .data, the CPU isn't smart enough to know that's data and not instructions. The seg fault is happening likely because the CPU is attempting to execute the string itself, as though it were instructions. In assembly, the order you type things is taken very literally.

section .text   
    global _start

_start:
   mov eax, len         ;message length
loop_top:
   push eax
       mov  edx, msg    ;message to write
       mov  ecx, len    ;message length
       mov  ebx,1       ;file descriptor (stdout)
       mov  eax,4       ;system call number (sys_write)
       int  0x80        ;trigger system call
   pop eax
   dec al               ;subtract 1 from AL
   jnz loop_top         ;if nonzero, do it again

   
   ;;your exit syscall needs to go here or you'll segfault.

section .data
        
    msg  db  'Hello there!' ,0xa;the string of we want to pass
    len  equ  $ - msg         ;length of our string

This isn't the most optimal way to do it, but it's a quick and dirty example.

  • Related