0

I'm trying to write a program that takes a string input of two words, then reverses the order of the words and prints them. Right now I'm struggling with a few problems because the teacher didn't teach us how to write x86 assembly very well.

Currently I'm trying to figure out how to:

  1. Find the start of the array again, as I believe the current program messes with the stack, and printing ♣ at 8(%esp,%ebx) when %ebx = 0
  2. How to store %ebx when the index hits the space, preferably into the register of %ecx, though I do not know how to prevent _printf from messing with %ecx in the current set up
  3. Lastly, whenever I input two words where the first word is smaller than 3 letters it doesn't output the 2nd word.

Right now, this is the output of my program (when the input is "Hello World")

Enter a string:
Hello World (input)
Your string is:
Hello World
Index of Space is = 6
World♣ <--- Supposed to be World Hello, in this case just testing to make sure I can find the 1st element of %eax

The registers I am currently using are %eax for the string array, and %ebx for the index of %eax. I would like to use %ecx, or any other register to store %ebx value when %ebx hits the space character.

Here is my x86 Assembly code so far:

LC0:
    .ascii "Enter a string: \0"
LC1:
    .ascii "%[^\n]\0"
LC2:
    .ascii "Your string is:\12\0"
LC3:
    .ascii "\12Index of Space is = %d\12\0"
LC4:
    .ascii "%c\0"  # print out the character 
LC6:
    .ascii "Yeehaw!\0" # test message
    
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    pushl   %ebp
    movl    %esp, %ebp
    
    pushl   %ebx
    subl    $112, %esp
    
    movl    $LC0, (%esp)
    call    _puts                # similar to _printf function
    leal    8(%esp), %eax
    movl    %eax, 4(%esp)
    
    movl    $LC1, (%esp)
    call    _scanf               # get string 
    
    movl    $LC2, (%esp)
    call    _printf              # printout the output text of LC2
    
            ###### A[i] ###### ebx is the index 
    movl    $0, %ebx             #index of array i=0    
    movl    $0, %ecx # Where I want to store space index
    jmp     .L2
    
.L1: #TEXT PORTION
    movsbl  %al, %eax           # eax =FFFFFFXX  XX means for each character print out the input character 
    incl    %ebx                # next index of array 
    

    movl    %eax, 4(%esp)       # print out from the first element of the array
    movl    $LC4, (%esp)
    call    _printf
        
.L2: #TEXT PORTION
    movzbl  8(%esp,%ebx), %eax  # the value of esp+8+0 strating address of the array to eax
    
    cmpb $0x20, %al # compare eax to see if it is a space
    jne .EndOfLine
    
    movl %ebx, 8(%esp) # Save space index
    
    
.EndOfLine:
    testb   %al, %al            # if eax is not equal to zero jump to L3, if is zero menas end of the string 
    jne     .L1 
    
    movl    8(%esp), %ebx # Take space index back
    incl    %ebx
    
    #States space index
    movl    %ebx, 4(%esp)       # print out from the first element of the array
    movl    $LC3, (%esp)
    call    _printf
    
    jmp .T2
.T1: #TEXT PORTION
    movsbl  %al, %eax           # eax =FFFFFFXX  XX means for each character print out the input character 
    incl    %ebx                # next index of array 
    
    movl    %eax, 4(%esp)       # print out from the first element of the array
    movl    $LC4, (%esp)
    call    _printf
        
.T2: #TEXT PORTION
    movzbl  8(%esp,%ebx), %eax  # the value of esp+8+0 strating address of the array to eax
    
    testb   %al, %al            # if eax is not equal to zero jump to L3, if is zero menas end of the string 
    jne     .T1

.Test:
    #Test to find initial array value, currently prints ♣ at 8(%esp,$0)
    movl    $0, %ebx
    movzbl  8(%esp,%ebx), %eax
    movsbl  %al, %eax
    movl    %eax, 4(%esp)
    movl    $LC4, (%esp)
    call    _printf

    
    
.Done:
    
    movl    $0, %eax
    addl    $112, %esp
    leave
    ret

Any help would be appreciated, and if explain why I need to do certain things since my teacher wasn't the best at explaining topics like the stack and such.

UPDATE: 8(%esp,%ebx) when ebx is 0 properly locates the initial letter, and using $116(%esp) as a local variable to store %ebx.

MHasting
  • 1
  • 1
  • 1
    Save `ecx` on the stack. There is no way to stop `printf` from modifying it. The calling convention says `eax`, `ecx` and `edx` are caller saved. Note if you decide to use a preserved register you will also need to save that for your caller so you are going to have to use the stack in any case. – Jester Dec 10 '21 at 01:14
  • My only problem is I'm not sure how exactly to properly save it on the stack without messing up the entire thing as this is the first time I've had to play around with the stack like this before. I know that I'm supposed to use push/pop, but anywhere I place it I mess up the array or %ebx prints the wrong value. – MHasting Dec 10 '21 at 01:18
  • Change `subl $112, %esp` to `116` and then you can use `112(%esp)` as a new local variable. Note that the code is already broken because the `push %ebx` has no matching `pop` so while the stack is balanced by the `leave` you do not preserve `ebx` and violate calling convention. Also reading with an unlimited format string is prone to buffer overflow. – Jester Dec 10 '21 at 01:28
  • Just changed $112 to 116 and removed push %ebx (not sure how that snuck in there), right now I'm just trying to figure out how to properly loop until the space for the first word and it should be good. – MHasting Dec 10 '21 at 01:43
  • Or just don't use ECX for something that has to survive across function calls. Use EDI and/or ESI, which like EBX are [call-preserved](https://stackoverflow.com/questions/9268586/what-are-callee-and-caller-saved-registers/56178078#56178078) in mainstream 32-bit x86 calling conventions. That's easier and more efficient than spilling/reloading ECX around printf, whether with push/pop or with mov. – Peter Cordes Dec 10 '21 at 03:00

0 Answers0