I wrote this code in assembly for an assignment in university and for some reason it prints an extra new line and unnecessary spaces…
Here is the code, it is documented and spread across 2 different files. the main idea of them is reciving a choice from the user and entering 1 of 3 functions. the code mainly deals with strings and switching characters. Here is the first file:
.extern printf
.extern scanf
.extern pstrlen
.extern swapCase
.extern pstrijcpy
declaring strings to use in rodata
.section .rodata
length_mess: .string “first pstring length: %d, second pstring length: %dn”
swap_case_mess: .string “length: %d, string: %sn”
invalid_mess: .string “invalid option!n”
msg_input: .string “What is your guess?n”
print_mess: .string “length: %d, string: %snlength: %d, string: %sn”
invalid_index_msg: .string “invalid input!n”
format: .string “%d”
# declaring run_func
.section .text
.global run_func
.type run_func, @function
run_func:
# Enter
pushq %rbp
movq %rsp, %rbp
# Compare number to 31
compare_31:
cmpq $31, %rdi
# when number is not 31
jne compare_33
# when choice is 31
# move first string to first arg
movq %rsi, %rdi
xorq %rax, %rax
call pstrlen
# move result to another reg
movq %rax, %r13
# move second string to first arg
movq %rdx, %rdi
xorq %rax, %rax
call pstrlen
# move result to another reg
movq %rax, %r14
# Print length message with suitable args
movq $length_mess, %rdi
movq %r13, %rsi
movq %r14, %rdx
xorq %rax, %rax
call printf
mov %rbp, %rsp
pop %rbp
ret
compare_33:
# check if choice is 33
cmpq $33, %rdi
jne compare_34
# call swap case with fist pstr
movq %rsi, %rdi
xorq %rax, %rax
call swapCase
# clean rbx and move swapped string to rbx
xorq %rbx, %rbx
movq %rax, %rbx
# call swap case with second pstr
movq %rdx, %rdi
xorq %rax, %rax
call swapCase
# clean r12 and move second swapped string to r12
xorq %r12, %r12
movq %rax, %r12
print_swap:
# get the length of first string into r13
movq %rbx, %rdi
xorq %rax, %rax
call pstrlen
xorq %r13, %r13
movq %rax, %r13
# get the length of second string into r14
movq %r12, %rdi
xorq %rax, %rax
call pstrlen
xorq %r14, %r14
movq %rax, %r14
# print the first swapped string
movq $print_mess, %rdi
movq %r13, %rsi
movq %rbx, %rdx
xorq %rax, %rax
call printf
# print the second swapped string
movq $print_mess, %rdi
movq %r14, %rsi
movq %r12, %rdx
xorq %rax, %rax
call printf
jmp end
compare_34:
cmpq $34, %rdi
jne invalid_input
xorq %rax, %rax
# dest
movq %rsi, %r15
# src
movq %rdx, %r14
sub $16, %rsp
# Rest of scanf calls
movq $format, %rdi
movq %rsp, %rsi # pass address of i to scanf
movq $0, %rax
call scanf
# Save i in r12
movl -16(%rbp), %r12d
# move rsp back to rbp
movq %rbp, %rsp
# move rsp to save in stack
sub $16, %rsp
# index j
movq $format, %rdi
movq %rsp, %rsi
xorq %rax, %rax
call scanf
# Save j in r13
movl -16(%rbp), %r13d
# move rsp back to rbp
movq %rbp, %rsp
# get the length of dest
movq %r15, %rdi
xorq %rax, %rax
call pstrlen
# move len 1 to rbx
movq %rax, %rbx
# check that j isn't more than length of dest
cmpq %rbx, %r13
# j - len1 >= 0
jg invalid_index
# get the length of src
movq %r14, %rdi
xorq %rax, %rax
call pstrlen
xorq %rbx, %rbx
# check that j isnt more than length of src
cmpq %rax, %r13
# j - len2 >= 0
jg invalid_index
# check that i is less j
cmpq %r12, %r13
# j - i < 0
jl invalid_index
# move dest into rdi, first function input
movq %r15, %rdi
# move src into rsi for second input
movq %r14, %rsi
# move i into rdx 3rd arg
movq %r12, %rdx
# move j into rcx 4th arg
movq %r13, %rcx
call pstrijcpy
# move the transfomred string to r15
movq %rax, %r15
jmp print
print:
# get first length
movq %r15, %rdi
xorq %rax, %rax
call pstrlen
movq %rax, %r13
# get second length
movq %r14, %rdi
xorq %rax, %rax
call pstrlen
movq %rax, %r12
# print length and first string
movq $print_mess, %rdi
# length to rsi
movq %r13, %rsi
# string to rdx
movq %r15, %rdx
movq %r12, %rcx
movq %r14, %r8
xorq %rax, %rax
call printf
jmp end
invalid_index:
movq $invalid_index_msg, %rdi
xorq %rax, %rax
call printf
# jump to print and print regular strings with no changes
jmp print
# print when the user inserted wrong choice
invalid_input:
movq $invalid_mess, %rdi
xorq %rax, %rax
call printf
end:
mov %rbp, %rsp
pop %rbp
ret
Here is the second file:
.section .rodata
msg_inval: .string “invalid input!n”
.section .text
.global pstrlen
.type pstrlen, @function
pstrlen:
pushq %rbp
movq %rsp, %rbp
xorq %rax, %rax
# move the first arg in struct memory to return value
movzbq (%rdi), %rax
mov %rsp, %rbp
pop %rbp
ret
.global swapCase
.type swapCase, @function
swapCase:
pushq %rbp
movq %rsp, %rbp
xorq %rax, %rax
# move the input pointer to rcx
movq %rdi, %rcx
# move in the struct formation to the string itself
inc %rcx
swaploop:
# get the first char of the string in rcx to compare
movzbl (%rcx), %eax
# compare using the smallest size of the register %rax
cmp $0, %al
je end_swap
# check if the char is potentially lower or upper
cmp $96, %al
jle lower_case
jg upper_case
# check if the char is actually a character or just a sign
lower_case:
cmp $65, %al
jge letter_lower
jl no_letter
# check again if its a letter
letter_lower:
cmp $90, %al
jg no_letter
# add 32 to offset into lower letters
addb $32, (%rcx)
# increment rcx and jump to the next letter loop
inc %rcx
jmp swaploop
# no letter, continue to the next letter
no_letter:
inc %rcx
jmp swaploop
# check if it is upper
upper_case:
cmp $122, %al
jg no_letter
subb $32, (%rcx)
inc %rcx
jmp swaploop
# end the run of swapcase
end_swap:
movq %rdi, %rax
mov %rbp, %rsp
pop %rbp
ret
.global pstrijcpy
.type pstrijcpy, @function
pstrijcpy:
pushq %rbp
movq %rsp, %rbp
xorq %rax, %rax
xorq %r11, %r11
# put dest in r13
movq %rdi, %r13
movq %rdi, %rbx
# clean r12 for counter and increment rdi and rsi to skip the [len]
xorq %r12, %r12
inc %rdi
inc %rsi
# loop till we reach ith index on both strings
loop1:
cmpq %r12, %rdx # comapre to i
je loop2
inc %r12
inc %rsi
inc %rdi
jmp loop1
# loop and switch between characters till the jth index
loop2:
cmpq %r12, %rcx # compare to j
jl end
# move current byte of string2 to al
movb (%rsi), %r11b
# replace to current byte of string1
movb %r11b,(%rdi)
inc %r12
inc %rsi
inc %rdi
jmp loop2
end:
movq %rbx, %rax
mov %rbp, %rsp
pop %rbp
ret
The problem is at choice 34, pstrijcpy. the goal is to copy characters from 1 string to the other from the ith index to the jth index. for the next input this is what happens:
Enter Pstring length: 11
Enter Pstring: Hello World
Enter Pstring length: 5
Enter Pstring: BBBBB
Choose a function:
31. pstrlen
33. swapCase
34. pstrijcpy
34
1
4
length: 11, string:
HBBBB World
length: 5, string: BBBBB
the problem is near “HBBBB World”, would appreciate any help. I have no idea why the new line and spaces happen.
thanks.
it happens on both strings, so the problem isn’t only with the first one. Debugging shows that the strings do change accordingly. meaning in the example above we got:
Hello World
HBllo World
HBBlo World
HBBBo World
returned: HBBBB World
Tried playing with the printf formatting as well, didn’t change anything. Tried changing registers which of course didn’t do much
again, thanks 🙂