0

I'm in need to convert the letters of a string to the corresponding order in alphabet, (ex: A -> 1, B -> 2, etc.)

In this example, the string I have to convert is: "mostra os objetos e os morfismos", I tried a lot of things, but nothing worked. It seems like I get the ascii value of the char, but when I add it back on the string it prints the corresponding last 2 dec digits in ascii, ex: (m which in dec is 0155 prints - that is 55 in ascii)

here is my code:

SYS_EXIT  equ 1
SYS_WRITE equ 4
STDIN     equ 0
STDOUT    equ 1

global    _start

section   .text
_start:
qe:
    mov         eax, SYS_WRITE                  ;  
    mov         ebx, STDOUT                     ; 
    mov         ecx, e                          ;
    mov         edx, len                      ; 
    int 0x80                                    ; 

    mov         rdi, string                     ; 
    mov         rdx, string_e                     ; 
    mov         r9, 0                           ;      
    jmp         loop_e

next:
    mov         [rdx], esp                      ; write single character
    inc         rdx                             ; advance pointer to next cell to write
    inc         rdi                             ; advance pointer to next cell to write
    inc         r9                              ; "count" number so far on 
    cmp         r9, len_string                    ; did we reach the number of stars for this line?
    jne         loop_e                            ; not yet, keep writing on this line
    jmp         result_e


loop_e:
    mov         esp, [rdi]
    cmp         byte [rdi], ' '
    je          next
    xor         esp, 40H
    mov         [rdx], esp                      ; write single character

    inc         rdx                             ; advance pointer to next cell to write
    inc         rdi                             ; advance pointer to next cell to write
    inc         r9                              ; "count" number so far on line

    cmp         r9, len_string                    ; did we reach the number of stars for this line?
    jne         loop_e                            ; not yet, keep writing on this line
    jmp         result_e


result_e:
    mov         eax, SYS_WRITE                  ; system call number for write (SYS_WRITE)
    mov         ebx, STDOUT                     ; system call number for file handle (STDOUT)
    mov         ecx, string                          ; address of string to output
    mov         edx, len_string                      ; number of bytes
    int 0x80

    mov         eax, SYS_WRITE                  ; system call number for write (SYS_WRITE)
    mov         ebx, STDOUT                     ; system call number for file handle (STDOUT)
    mov         ecx, lbreak                          ; address of string to output
    mov         edx, 1                      ; number of bytes
    int 0x80

    mov         eax, SYS_WRITE                  ; system call number for write (SYS_WRITE)
    mov         ebx, STDOUT                     ; system call number for file handle (STDOUT)
    mov         ecx, string_e                          ; address of string to output
    mov         edx, len_string                      ; number of bytes
    int 0x80

    mov         eax, SYS_WRITE                  ; system call number for write (SYS_WRITE)
    mov         ebx, STDOUT                     ; system call number for file handle (STDOUT)
    mov         ecx, lbreak                          ; address of string to output
    mov         edx, 1                      ; number of bytes
    int 0x80

    jmp         _finish
    
_finish:
    mov eax,SYS_EXIT                            ;system call number (SYS_EXIT)
    int 0x80                                    ;call kernel
    ret

section   .data
e:              db        "e.", 0xA,0xD
len             equ       $ - e


string:         db        "mostra os objetos e os morfismos", 0
lbreak:         db        0xA,0xD


section   .bss
string:                     resb        44
string_e:                   resb        44

zero                        equ         0
len_string                  equ         32

my output:

e.
mostra os objetos e os morfismos
-/342! /3 /"*%4/3 % /3 -/2&)3-/3

what I expect:

e.
mostra os objetos e os morfismos
13151920181 1519 152105201519 5 1519 1315186919131519
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Cesar Lopes
  • 373
  • 1
  • 10
  • 2
    For starters, you definitely don't want to use `esp` as a general purpose register. It's the stack pointer. Even if it happens to work, just don't :) Also it's 32 bit and you want a 8 bit register. So maybe use `al` or something. Next, you want to subtract `40h` not `xor` to get the index. To print that you need to convert to text. For single digits adding `30h` works but for two digits that's not good enough. What format do you even want the output? – Jester Jun 22 '22 at 20:37
  • Just edited the question with the expected output. I got the al part, I'll fix it. I'm new in assembly gonna try using this tip in the next codes. but the single digits adding 30h part do you mean, O for ex is the 15º letter, when I try to put it the position of O it is not gonna work because it is a 2 char ? – Cesar Lopes Jun 22 '22 at 20:44
  • 1
    Exactly, you can't fit `15` which is 2 digits into the position of `O` which is a single character. But since you use a different buffer, just allocate that twice the size (for worst case). In the code you can divide the index by 10 and if the quotient is not zero you write that into the output first. – Jester Jun 22 '22 at 20:56
  • Just got what you said, actually not adding 30H, but sub 30H shows from 1-9. I just did for a-j. Got the Result: "mostr1 os o2j5tos 5 os mor69smos". I just don't know how am I gonna do to convert the al value to a string and add to my buffer the >=10 values, any ideas? – Cesar Lopes Jun 22 '22 at 21:29
  • 1
    As I said, divide by 10. Use the quotient and the remainder for the two digits. Do not add a leading zero. – Jester Jun 22 '22 at 21:32
  • 1
    just finished, Thank you @Jester, I didn't divide, couldn't pass al for ax, I just hate Assembly jajajaja... I created 2 labels, one for 10-19 and other for 20+, moved the decimal as an cost and sub 10-19 for 3AH, and 20+ for 44H – Cesar Lopes Jun 22 '22 at 22:37
  • That might actually be faster in this case. – Jester Jun 22 '22 at 23:05
  • 1
    Your output format is ambiguous between `aa` (11) and `k` (11). But see [What is the idea behind ^= 32, that converts lowercase letters to upper and vice versa?](https://stackoverflow.com/a/54585515) for efficient case-insensitive ASCII -> alphabet_index. (Although IIRC my answer there shows zero-based.) Anyway, you should be using OR or AND, not XOR. For int->string in general, see [How do I print an integer in Assembly Level Programming without printf from the c library?](https://stackoverflow.com/a/46301894) although as you found, you can special-case 1 to 2 digit numbers. – Peter Cordes Jun 22 '22 at 23:56
  • Also, [What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/q/46087730) - if you want to use `int 0x80` instead of `syscall`, you should normally be writing 32-bit code. – Peter Cordes Jun 22 '22 at 23:56
  • Also: `mov esp, [rdi]` - don't use the stack pointer as a temporary register!!! You have 15 other registers, including r8d..r9d. – Peter Cordes Jun 22 '22 at 23:59

0 Answers0