Я пытаюсь написать программу, которая преобразует строчную строку символов в верхний регистр, используя буфер для хранения начальной строки. Проблема, с которой я столкнулся, заключается в том, что моя программа будет печатать бесконечный цикл символов, которые должны соответствовать последовательности, которую я ему дал.Введите строку символов и вывод в верхний регистр
Другие проблемы, которые я считаю, существуют в коде следующим образом:
Некоторые подпрограммы используют
ret
в конце вызова. Проблема, с которой у меня возникают проблемы, заключается в том, что вы обнаруживаете , который этих подпрограмм действительно не нуженret
, и их лучше использовать сjmp
. Честно говоря, я немного запутался здесь между семантикой этих двух. Например, подпрограмма, вызываемая сja
, должна бытьret
'ed в конце вызова?Я также пытаюсь напечатать количество итераций, которые происходят в каждой итерации цикла, используемого для преобразования значений. По какой-то причине я сделаю счетчик и решит его распечатать с помощью рутинной игры
PrintNumIter
, которая, к сожалению, ничего не делает.
Полная программа заключается в следующем.
Codez
bits 32
[section .bss]
buf: resb 1024 ;allocate 1024 bytes of memory to buf
[section .data]
;*************
;* CONSTANTS *
;*************
;ASCII comparison/conversion
LowercaseA: equ 0x61
LowercaseZ: equ 0x7A
SubToUppercase: equ 0x20
;IO specifiers/descriptors
EOF: equ 0x0
sys_read: equ 0x3
sys_write: equ 0x4
stdin: equ 0x0
stdout: equ 0x1
stderr: equ 0x2
;Kernel Commands/Program Directives
_exit: equ 0x1
exit_success: equ 0x0
execute_cmd: equ 0x80
;Memory Usage
buflen: equ 0x400 ;1KB of memory
;*****************
;* NON-CONSTANTS *
;*****************
iteration_count: db 0
query : db "Please enter a string of lowercase characters, and I will output them for you in uppercase ^.^: ", 10
querylen : equ $-query
[section .text]
global _start
;===========================================
; Entry Point
;===========================================
_start:
nop ;keep GDB from complaining
call AskUser
call Read
call SetupBuf
call Scan
call Write
jmp Exit
;===========================================
; IO Instructions
;===========================================
Read:
mov eax, sys_read ;we're going to read in something
mov ebx, stdin ;where we obtain this is from stdin
mov ecx, buf ;read data into buf
mov edx, buflen ;amount of data to read
int execute_cmd ;invoke kernel to do its bidding
ret
Write:
mov eax, sys_write ;we're going to write something
mov ebx, stdout ;where we output this is going to be in stdout
mov ecx, buf ;buf goes into ecx; thus, whatever is in ecx gets written out to
mov edx, buflen ;write the entire buf
int execute_cmd ;invoke kernel to do its bidding
ret
AskUser:
mov eax, sys_write
mov ebx, stdout
mov ecx, query
mov edx, querylen
int execute_cmd
ret
PrintNumIter:
mov eax, sys_write
mov ebx, stdout
push ecx ;save ecx's address
mov ecx, iteration_count ;print the value of iteration_count
mov edx, 4 ;print 4 bytes of data
int execute_cmd
pop ecx ;grab the value back in
ret
;===========================================
; Program Preperation
;===========================================
SetupBuf:
mov ecx, esi ;place the number of bytes read into ecx
mov ebp, buf ;place the address of buf into ebp
dec ebp ;decrement buf by 1 to prevent "off by one" error
ret
;===========================================
; Conversion Routines
;===========================================
ToUpper:
sub dword [ebp + ecx], SubToLowercase ;grab the address of buf and sub its value to create uppercase character
Scan:
call PrintNumIter ;print the current iteration within the loop
cmp dword [ebp + ecx], LowercaseA ;Test input char against lowercase 'a'
jb ToUpper ;If below 'a' in ASCII, then is not lowercase - goto ToLower
cmp dword [ebp + ecx], LowercaseZ ;Test input char against lowercase 'z'
ja ToUpper ;If above 'z' in ASCII, then is not lowercase - goto ToLower
dec ecx ;decrement ecx by one, so we can get the next character
inc byte [iteration_count] ;increment the __value__ in iteration count by 1
jnz Scan ;if ecx != 0, then continue the process
ret
;===========================================
;Next:
; dec ecx ;decrement ecx by one
; jnz Scan ;if ecx != 0 scan
; ret
;===========================================
Exit:
mov eax, _exit
mov ebx, exit_success
int execute_cmd
Вы должны использовать отладчик для пошагового вашей программы, чтобы выяснить, где его поведение отклоняется от того, что вы ожидаете. –
Отлажено много; Я только начал изучать сборку x86. Проверяли регистры и адреса, а что нет. Знаете ли вы, как хорошо? – zeboidlund
Если вы прошли через код, предположительно, вы нашли одну (или несколько) конкретных строк, которые не выполняют то, что вы ожидали/планировали? –