Как использовать строки в emu8086

Мне нужна помощь со строками в emu8086. Я инициализировал строку:

str1 db "0neWord" 

И у меня пустая строка:

 str2 db ? 

Теперь мне нужно проверить все буквы в str1 и скопировать на str2 , но если буква в str1 равна 0, мне нужно заменить ее на O. Если нет, мне нужно просто скопировать письмо.

Как я могу это сделать?

str2 db ? не является пустой строкой. db означает «define byte» , и что ? означает одиночный неинициализированный байт.

db "0neWord" является ассемблером, он будет скомпилирован в последовательности байтов, определенных как '0', 'n', 'e', ..., 'd' . В ассемблере нет типа «строка», все скомпилировано в машинный код, который можно рассматривать как ряд байтов. То, что «тип» данных хранится в памяти, зависит от инструкций, используемых для их доступа, но в памяти все это всего лишь серия байтов и может рассматриваться как таковая.

Вероятно, это подходящее время для проверки документации отладчика emu8086 и просмотра памяти по адресу str1 после загрузки кода в отладчик, чтобы увидеть, как он скомпилировался.

Итак, как только вы скопируете второй байт с str1 на str2 , вы начнете перезаписывать некоторую память, которую вы не ожидали перезаписывать.

Чтобы выделить некоторый буфер памяти фиксированного размера, вы можете использовать, например, str2 db 100 DUP(?) Выполняющий 100 раз ? определение на db , таким образом, сохраняя там 100 байт памяти, последующие байты машинного кода в том же разделе будут скомпилированы за адресом str2+100 .


Чтобы сделать что-либо с str1 “string”, вам нужно знать:

1) его адрес в памяти, ассемблер x86 имеет много способов, как получить это, но два самых простых:

  • mov ,OFFSET str1 (r16 – любой регистр 16b)
  • lea ,[str1] (делает то же самое в этом случае)

2) его размер ИЛИ структура. Вы не поместили какую-либо структуру там, как строки с nul-terminated имеют байты со значением 0 в конце или DOS int 21h, ah=9 для отображения строки ожидает, что строка завершена знаком доллара '$' и т. Д. Поэтому вам нужно по крайней мере, размер. И директива EQU для ассемблера и «текущая позиция» могут использоваться для вычисления размера str1 следующим образом:

 str1 db "0neWord" str1size EQU $-str1 ; "$" is assemblers "current_address" counter 

Хм, я попытался проверить это во-первых, прочитав некоторые документы, но мне очень сложно найти хорошую документальную документацию emu8086 (найти что-то вроде «ссылки», и это полностью отсутствует описание директив ассемблера).

Интересно, почему так много людей все еще приземляются на это, а не linux + nasm / подобные, которые полностью бесплатны, с открытым исходным кодом и документированы.

Поэтому давайте надеяться, что emu8086 будет работать как MASM / TASM, и что я до сих пор помню этот синтаксис правильно, тогда указанное определение размера должно работать. В противном случае обратитесь к своим примерам / документам.


Наконец, когда у вас есть адрес, размер и достаточно большой целевой буфер (снова для загрузки его адреса вы можете использовать OFFSET или lea в emu8086), вы можете запрограммировать свою задачу, например, следующим образом:

  ; pseudo code follows, replace it by actual x86 instructions ; and registers as you wish ; ("r16_something" means one of 16b register, r8 is 8b register) lea r16_str1,[str1] ; load CPU with address of str1 mov r16_counter,str1size ; load CPU with str1 size value lea r16_str2,[str2] ; load address of target buffer loop_per_character: mov r8_char,[r16_str1] ; read single character cmp r8_char,'0' jne skip_non_ascii_zero_char ; the character is equal to ASCII '0' character (value 48) mov r8_char,'O' ; replace it with 'O' skip_non_ascii_zero_char: ; here the character was modified as needed, write it to str2 buffer mov [r16_str2],r8_char ; make both str1/2 pointers to point to next character inc r16_str1 inc r16_str2 ; count down the counter, and loop until zero is reached dec r16_counter jnz loop_per_character ; the memory starting at "str2" should now contain ; modified copy of "str1" ; ... add exit instructions ... 

Хм .. получается, что «псевдокод» – это полный код x86, вам просто нужно назначить реальные регистры псевдоним и заменить их всюду в источнике.

Я попытался дать очень обширные комментарии (по моему мнению), поэтому можно понять каждую используемую инструкцию. Вы должны проконсультироваться с каждым из руководств по инструкциям Intel, перекрестив их с любым учебным пособием / уроками, которые вы можете получить для Ассамблеи, пока не почувствуете, что вы понимаете, что такое регистр, память и т. Д.

Также отлаживайте инструкцию по команде, проверяя состояние CPU (значения регистра, флаги) и содержимое памяти после каждой инструкции, чтобы получить представление о том, как она работает.

Существует несколько способов сделать это. Вот некоторые примеры:

1) С инструкцией по строкам:

 .model small .data str1 db "0neWord$" size equ $-str1 str2 db size dup ('') .code main: mov ax, @data mov ds, ax mov cx, size cld ; DF might have been set, but we want lodsb to go forwards lea si, str1 mov ax, 0 mov bx, 0 copyStr: lodsb ;str1 to al cmp al, '0' je alterChar mov str2[bx], al jmp continue alterChar: mov str2[bx], 'o' continue: inc bx loop copyStr mov str2[bx], '$' mov ah, 09h lea dx, str2 int 21h mov ah, 04ch int 21h end main 

2) Без строковой инструкции:

 .model small .data str1 db "0neWord$" str2 db ? .code main: mov ax, @data mov ds, ax mov si, 0 call copyStr mov ah, 09h lea dx, str2 int 21h mov ah, 04ch int 21h copyStr proc mov bx, 0 compute: mov bl, str1 [si] cmp bl, '0' je alterChar mov str2[si], bl jmp continue alterChar: mov str2 [si], 'o' continue: inc si cmp str1[si], '$' je return jmp compute return: mov str2[si], '$' ret copyStr endp end main 

Инструкцию LODSB вы можете узнать больше о строковых инструкциях отсюда

3) С lodsb / stosb и упрощенным / оптимизированным:

 .model small .data str1 db "0neWord$" size equ $-str1 str2 db size dup ('') .code main: mov ax, @data mov ds, ax mov es, ax ; stosb stores to [es:di] mov si, OFFSET str1 mov di, OFFSET str2 cld ; make sure stosb/lodsb go forwards ; copy SI to DI, including the terminating '$' copyStr: ; do { lodsb ; str1 to al cmp al, '0' je alterChar doneAlteration: stosb ; al to str2 cmp al, '$' jne copyStr ; } while(c != '$') mov ah, 09h ; print implicit-length string mov dx, OFFSET str2 int 21h mov ah, 04ch ; exit int 21h alterChar: mov al, 'o' ;jmp doneAlteration stosb jmp copyStr end main 
  • Как повернуть экран эмулятора Android?
  • Почему я получил сообщение об отключенном эмуляторе-5554
  • Службы Google Play, отсутствующие в эмуляторе (Android 4.4.2)
  • Как получить знак, мантисса и показатель числа с плавающей запятой
  • Android - Сохранить изображение с URL на SD-карту
  • Симулятор или эмулятор? В чем разница?
  • Давайте будем гением компьютера.