Что может заставить программу на ассемблере отображать «мусор»? - PullRequest
0 голосов
/ 18 сентября 2008

У меня есть код, который должен отображать короткое сообщение. Вот соответствующий код:

DATA    SEGMENT 'DATA'
MSG DB  0AH, 0DH, 'Hello, Adam', '$'
CHAR    DB  00H
DATA ENDS

CODE    SEGMENT 'CODE'
PRINT_MSG:
    MOV AH, 09H ;Command to print string of characters
    MOV DX, OFFSET MSG  ;Mov address of message into DX
    INT 21H     ;DOS Interrupt
    JMP WAITING ;Loop back to waiting state
CODE ENDS

И вывод:

E:\ece323\software\lab2>MAIN.EXE
?F ^?¶ ? N?   ?               -!-

Hello, Adam-

Что здесь происходит?

Ответы [ 5 ]

2 голосов
/ 18 сентября 2008

Я предполагаю, что ваш DS не указывает на ваш сегмент данных.

Int21 Функция 0x09 берет строку из DS: DX.

Помните, что DX является только 16-битным регистром. Для доступа к данным за пределами 16-битного диапазона вы должны использовать регистры сегментов. Они называются DS и ES для данных, CS для кода и SS для стека (есть также FS и GS на i386).

Точный адрес, с которого вы загружаете, задается как 16 * сегмент_регистр + смещение_регистр. Int21 не может угадать, где находится ваш DS, поэтому вы должны загрузить его до вызова прерывания.

Полагаю, вы никогда не инициализировали свой регистр DS, поэтому он, скорее всего, указывает на код, а не на сегмент данных.

Попробуйте заменить свой

  MOV DX, offset MSG

по:

  LDS DX, MSG  ; Check that, it's been ages since I've written 16 bit code.

К сожалению, прошли годы с тех пор, как я последний раз играл с 16-битным ассемблером, поэтому я не могу это проверить, но LDS должен сделать свое дело.

Вы также можете косвенно загрузить DS при запуске вашей программы примерно так:

  MOV AX, SEG DATA  ; check that - can be SEGMENT or so as well.
  MOV DS, AX
0 голосов
/ 01 декабря 2010

Похоже, вы отображаете часть PSP. Это случайно .COM случайно? Если вы забудете директиву ORG 100h на ассемблере, OFFSET не укажут, где вы думаете, что должны ... Как примечание, что переключение с MOV OFFSET на LEA также будет "работать". MASM достаточно умен, чтобы понять, что вы делаете, когда используете LEA, тогда как с OFFSET это может быть не так (да, я научился всему этому нелегко давным-давно ... :-)).

0 голосов
/ 06 октября 2008

Нильс прав, регистр DS должен быть установлен для использования этой функции int 21. Сначала попробуйте вторую часть с переходом EAX, она должна работать наверняка.

И нет нужды в 0 символах после строки. 9-я функция не работает со строками с нулевым символом в конце, этот символ $ работает вместо 0.

0 голосов
/ 18 сентября 2008

Попробуйте следующее изменение:

DATA    SEGMENT 'DATA'
ERROR_MSG DB 'DS:DX is wrong'
MSG DB  0AH, 0DH, 'Hello, Adam', '$'
CHAR    DB      00H
DATA ENDS

Если отображается сообщение об ошибке, значит DS: DX неверно, поэтому либо DS не указывает на сегмент DATA, либо «OFFSET MSG» по какой-то причине неверно ... у меня asm ржавый, но вместо ADDR СМЕЩЕНИЕ (?)

Если сообщение об ошибке не отображается, проблема произошла до достижения PRINT_MSG.

0 голосов
/ 18 сентября 2008

Я предполагаю, что вы, вероятно, не работаете в "реальном" режиме, который необходим для работы программ MSDOS в целом (и прерываний Int 21h в частности) для работы.

Windows работает исключительно в «защищенном» режиме начиная с Windows 95; Командная строка работает в защищенном режиме, начиная с Windows 2000.

Возможно, вы захотите попробовать создать ярлык в EXE, а затем установить параметры совместимости в ярлыке.

...