Сравнение введенной строки со строками из структуры struct NASM
Мне нужно вывести из структуры номер строки, которая эквивалентна введенной строчке с консольного ввода, если таких строк нет, то написать сообщение об её отсутствии. Я не могу освоить эти структуры. Использую NASM на Win32, в качестве линкера golink. Вот мой код. Помогите, пожалуйста
global Start
STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10
EXTERN GetStdHandle
EXTERN WriteFile
EXTERN ExitProcess
EXTERN ReadConsoleA
extern lfwrit
section .text
Start:
;получение хэндла вывода
push dword STD_OUTPUT_HANDLE
call GetStdHandle
mov [hstdout],eax
mov eax, 1000h
;WriteFile(hstdout, txt, 7, &actlen, NULL)
push 0
push actlen
push msg_len
push msg
push dword [hstdout]
call WriteFile
;получение хэндла ввода
push dword STD_INPUT_HANDLE
call GetStdHandle
mov [hstdin],eax
;ReadConsoleInputA(hstdin,buf,buf_len,0);
push 0
push actlen2 ;Pointer to a DWORD for number of characters read to be returned
push 11
push string
push dword [hstdin]
call ReadConsoleA
mov esi, records
mov ecx, [records_count]
search:
`mov esi, [eax+record.txt]; беру текст`
mov edi, string; введенную строку
mov edx, 11; максимальная длина
cld
repe cmpsb; сравниваю строки
jecxz success
add eax, 15; добавляю 15 так как txt 11 байт + 4 байта num
loop search
;WriteFile(hstdout, txt, 7, &actlen, NULL)
;Fail
push 0
push actlen
push fail_msg_len
push fail_msg
push dword [hstdout]
call WriteFile
jmp _exit
success:
`mov ecx, esi; в есх адрес текста
add ecx, record.num;`
;WriteFile(hstdout, txt, 7, &actlen, NULL)
;num
push 0
push actlen
push dword 4
push ecx
push dword [hstdout]
call WriteFile
call lfwrit
_exit:
;ExitProcess(0)
push dword 0
call ExitProcess
section .bss
string resb 11; место для введенной строки
struc record;структура число - текст
.txt resb 11
.num resd 1
endstruc
section .data
;хэндлы
hstdout dd 0
hstdin dd 0
actlen dd 1; что-то для ввода
actlen2 dd 1; что-то для вывода
msg db 'Entex text: ', 0ah
msg_len equ $ - msg
fail_msg db 'Note with this text doestn exist', 0ah
fail_msg_len equ $ - fail_msg
;инициализация структуры
records:
istruc record
at record.txt, db 'odin'
at record.num, dd 1
iend
istruc record
at record.txt, db 'devyat'
at record.num, dd 9
iend
records_count dd 2
Не получается получить строку для сравнения в данном фрагменте
mov esi, [eax+record.txt]; беру текст
и не понимаю как, потом получить по этой строке num из структуры
mov ecx, esi; в есх адрес текста
add ecx, record.num;
после сборки и запуска при вводе строки програма зависает на секунду и завершается
Ответы (1 шт):
Не знаю как в NASM, но вот аналогичный алго на FASM'e (у них синтаксис почти схожий). Поскольку во всех структурах поля одинакового размера, то под текст резервируем 8 байт, а под номер dword = 4. Теперь на старте ставим указатель на первую структуру, и для перехода на следующую - просто в цикле прибавляем к этому указателю 12.
Если сравнение дало результат, то прибавив к указателю 8 (резерв для текста) и обернув его в квадратные скобки, берём значение из найденной структуры. Для ввода-вывода удобней использовать функции из msvcrt.dll, как в примере ниже:
format pe console
include 'win32ax.inc'
entry start
;//************
.data
;//<--------- Структуры (размер одной: 8+4=12 байт)
struct Record_1
txt db 'odin '
num dd 1
ends
struct Record_2
txt db 'devyat '
num dd 9
ends
;//<--------- Указатели на них
rec1 Record_1
rec2 Record_2
rec_count dd 2
buff db 16 dup(' ')
;//************
.code
start:
;// Запрос на ввод текста
cinvoke printf,<10,' Enter text: ',0>
;// Ввод текста длиною 8 символов в буфер
cinvoke scanf,<'%8s',0>,buff
;// scanf() вставляет терминальный нуль - уберём его
mov ecx,16 ;// размер буфера
mov edi,buff ;// его адрес
xor al,al ;// что искать = нуль
repne scasb ;// поиск AL в EDI..
mov byte[edi-1],' ' ;// заменить нуль на пробел!
;// Сравниваем ввод с текстом из структур
mov esi,rec1.txt ;// адрес первого txt-поля
@compare: ;//
mov ecx,8 ;// длина поиска (всего символов в поле)
mov edi,buff ;// юзерский ввод (с чем сравнивать)
push esi ;// (!)запомнить адрес очередной структуры
repe cmpsb ;// Compare.. по длине ECX
jcxz @ok ;// если нашли.
pop esi ;// иначе: снимаем указатель
add esi,12 ;// прыгаем на сл.структуру
dec [rec_count] ;// всего структур -1
jnz @compare ;// повторить, если не нуль
;// Ошибка поиска и на выход
cinvoke printf,<' Text not found!',0>
jmp @exit
;//<----------- ОК! ----------------------------->
@ok: pop esi ;// ESI = указатель на структуру с текстом
mov eax,[esi+8] ;// взять в EAX поле "num" из этой структуры
cinvoke printf,<' Text Found! Num = %d',0>,eax
@exit: cinvoke getch
cinvoke exit,0
;//************
section '.idata' import data readable
library msvcrt,'msvcrt.dll'
import msvcrt, printf,'printf',scanf,'scanf',getch,'_getch',exit,'exit'