Страница 1 из 4

Обьясните плиз

Добавлено: 14 янв 2008, 19:26
Apokal
Здраствуйте!
Я недавно начал изучать Ассемблер и у меня возникло несколько вопросов и проблем при написании програмы. Пишу я на masm32 очень простую програму которая выводит сообщение на экран, вот код:

.186
.model small
.data
Message db 'Hello!$'
.code
_start:
mov dx,offset Message
mov ah,09h
int 21h
end _start

И вот мои вопросы:
1. В том виде котором я написал код он ассемблируетса нормально но как только я заменяю .186 на .386 тут же высвечиваетса ошыбка:
Assembling: G:\masm32\Test_1.asm
G:\masm32\Test_1.asm(7) : error A2022: instruction operands must be the same size
2. Если убрать символ нижнего подчеркивания перед start то выйдет ошыбка:
Assembling: G:\masm32\Test_1.asm
G:\masm32\Test_1.asm(10) : warning A4023: with /coff switch, leading underscore required for start address : start
3. После того как я ассемблирую этот код ( при этом никаких ошыбок необнаружываетса ), я его соединяю с файлом obj но при этом тоже выдаетса ошыбка уже при линковке:
Test_1.obj : fatal error LNK 1190: invalid fixup found, type 0x0001
_
Link error


Помогите пожалуйста разобратса. Если неуспеваетсе ответить на все вопросы то ответьте хотя бы на №3 чтобы я понял почему код неработает. Заранее спасибо.

Re: Обьясните плиз

Добавлено: 15 янв 2008, 01:53
somewhere
&quot писал(а):1. В том виде котором я написал код он ассемблируетса нормально но как только я заменяю .186 на .386 тут же высвечиваетса ошыбка:
Assembling: G:\masm32\Test_1.asm
G:\masm32\Test_1.asm(7) : error A2022: instruction operands must be the same size
Директива .386 подразумевает после себя 32-разрядные инструкции и адрессацию. Т.е. теперь смещения станут 32 битные, и команда должна выглядеть как
mov edx, offset message
&quot писал(а):2. Если убрать символ нижнего подчеркивания перед start то выйдет ошыбка:
Assembling: G:\masm32\Test_1.asm
G:\masm32\Test_1.asm(10) : warning A4023: with /coff switch, leading underscore required for start address : start
По-умолчанию константа/метка start уже определена, рекомендуют добавить подчеркивание, или назвать по-другому
&quot писал(а):3. После того как я ассемблирую этот код ( при этом никаких ошыбок необнаружываетса ), я его соединяю с файлом obj но при этом тоже выдаетса ошыбка уже при линковке:
Test_1.obj : fatal error LNK 1190: invalid fixup found, type 0x0001
Данная ошибка мне не известна, она связана с неверным компоновочным модулем в объектом файле, что то видать не срослось между компилятором и линковщиком. Попробуйте поставить более свежий линковщик, который внятно поймет что там нацарапал этот ненавистный мною masm32

Re: Обьясните плиз

Добавлено: 15 янв 2008, 09:02
Apokal
Спасибо за ответ. Я поменял линковщик на более новый и теперь все работает.

Re: Обьясните плиз

Добавлено: 15 янв 2008, 23:59
Apokal
Опять нужна ваша помощь!
Пытаюсь написать програму которая выводит на экран число.
Вот код:

Код: Выделить всё

.186		
.model tiny	
.stack 100h	
.data		
Number = 2
Result db ''
.code
_start:
mov ax,@data
mov ds,ax

mov di,offset Result

mov ax,Number
mov ch,10
div ch
add ah,'0'
xchg al,ah
stosb
xchg al,ah
mov al,'$'
stosb

mov dx,di
mov ah,09h
int 21h
mov ax,4c01h
int 21h
end _start
Теперь мои вопросы:
№1. Насколько я понял две команды
mov ax,@data
mov ds,ax
это команды которые оределяют адрес сегмента кода. Обязательно ли их использывать? Просто я встречал код и без этих двух команд.

№2.
Правильно ли, что регистры SI и DI это регистры где хранятса смещение даных, которые должны быть перемещены (регистр SI) и смещение даных, куда должно будет шото помещено (регистр DI). Если это правильно то просто напишыте "Да". Я по этому определению и написал строку "mov di,offset Result" поскольку я буду в Result помещать другие данные.

№3
Главный вопрос:
В результате запуска програмы вместо цифры 2 выводиста всякий мусор и издаетса дикий писк :mad: Я так понимаю что неправильно перевел двоичное число в строку.
Я действовал за схемой делим на 10 к остатку прибавляем 30h или символ "0" и в итоге получаем ASCII код нужной цифры. Поскольку в описании команды div было указано что делимое должно по размеру быть в два раза больше делителя то 10 я занес в сh, поскольку ax это 16 бит --- то нам нада было 8 бит для делителя тоесть сh.
За тем же описанием было сказано, остаток хранитса в регистре ah. Я поменял местами ah и al и использывал команду stosb которая должна загрузить al в Result. Потом вернул все на место. Чтобы строка нормально выводилась в конце добавил знак $ таким же способом, тоесть занес его в al и использывал команду stosb. Потом просто загрузил в dx уже хранящиеся в di смещение Result'a и вызвал прерывание для вывода на экран --- но нечего неполучилось.

№4
Я хотел чтобы програма завершалась путем нажатия клавиш Сtrl+Break для этого занес в al 01, а в ah 4с --- но в итоге прога просто пропищала высветила шото непоянтное и сама закрылась недожыдаясь нажатия клавиш.


Помогите пожалуйста ещо раз!

Re: Обьясните плиз

Добавлено: 16 янв 2008, 09:50
somewhere
&quot писал(а):№1. Насколько я понял две команды
mov ax,@data
mov ds,ax
это команды которые оределяют адрес сегмента кода. Обязательно ли их использывать? Просто я встречал код и без этих двух команд.
Читайте в книжках про PSP-сегменты, там вполне понятно написано какими значениями будут инициализированы сегментные регистры при запуске программы, если вы не уверены - запишите значения вручную.
&quot писал(а):№2.
Правильно ли, что регистры SI и DI это регистры где хранятса смещение даных, которые должны быть перемещены (регистр SI) и смещение даных, куда должно будет шото помещено (регистр DI). Если это правильно то просто напишыте "Да". Я по этому определению и написал строку "mov di,offset Result" поскольку я буду в Result помещать другие данные.
Значения регистров SI и DI как смещений операндов источника и приемника обязательы лишь при использовании строковых команд, таких как MOVS, SCAS, CMPS, STOS, INS и т.д. Если вы не используете эти команды, смещения операндов источника и назначения можете загружать в любой регистр, для которого допустима адресация в реальном режиме. В защищенном режиме можете использовать любой регистр общего назначения.
&quot писал(а):№3
Главный вопрос:
В результате запуска програмы вместо цифры 2 выводиста всякий мусор и издаетса дикий писк Я так понимаю что неправильно перевел двоичное число в строку.
После последней команды Stosb, содержимое регистра DI указывает на первый байт после вашей строки. Затем вы подготавливаете параметры для вывода этой строки, но в регистре DX должно находиться смещение начала вашей строки а не конца. В результате выводиться то, что находиться после этой самой строки, а именно - ваш код, данные ОС и т.д., в которых по-любому где-то встречаеться символ с кодом 7, который для системы вывода означает команду выдать звуковой сигнал. Все это будет продолжаться до тек пор, пока не встретится символ "$".
&quot писал(а):№4
Я хотел чтобы програма завершалась путем нажатия клавиш Сtrl+Break для этого занес в al 01, а в ah 4с --- но в итоге прога просто пропищала высветила шото непоянтное и сама закрылась недожыдаясь нажатия клавиш.
А она и не должна ничего ждать, то что заноситься в AL будет доступно операционной системе как код ошибки, которую она может прочитать во внутренней переменной ERRORCODE и тем самым выполнять определенные действия. Читайте документацию к функциям MS-DOS и внимательно следите за содержимым регистров и все у вас получиться.

Re: Обьясните плиз

Добавлено: 16 янв 2008, 10:57
airyashov
Apokal писал(а):№1. Насколько я понял две команды
mov ax,@data
mov ds,ax
это команды которые оределяют адрес сегмента кода. Обязательно ли их использывать? Просто я встречал код и без этих двух команд.
определяют адрес сегмента данных
по умолчанию при загрузке указывает на PSP
для программ типа COM инициализация требуется, так как вся программа 1 сегмент

при использовании строковых комант обратите внимание с каким сегментом работает приемник, т.е. с чем в паре работает DI

Re: Обьясните плиз

Добавлено: 17 янв 2008, 16:35
Apokal
Спасибо что ответили.

Но у меня опять нечего неполучилось хотя прогрес кое какой есть. В коде я заменил строку mov dx,di на mov dx,offset Result. Но на экране тот же результат хотя мусора и писка стало раза в 3 меньше. Я даже скачал СodeView и там проследил за всемя регистрами ----- все происходило правильно и в конце в dx было смещение Result'a.
Единственное что, так это я незнаю как просмотреть содержимое Result'a. При попытке просмотреть в СodeView выдало сообщение:
"Expresion cannot be evaluated"

Re: Обьясните плиз

Добавлено: 17 янв 2008, 16:51
airyashov

Код: Выделить всё

.model small
.stack 100h	
.data		
Number = 2
Result db ' ','$'
.code

_start:

mov ax,@data
mov ds,ax
[B]mov es,ax[/B]
mov di,offset Result
mov dx,di

mov ax,Number
mov ch,10
div ch
add ah,'0'
xchg al,ah
stosb

mov ah,09h
int 21h
mov ax,4c00h
int 21h

end _start

Re: Обьясните плиз

Добавлено: 17 янв 2008, 16:51
somewhere
&quot писал(а):Result db ''
Размер этой переменной равен 0, по сути ее адрес такой же, как и у первой команды. Задайте фиксированное значение переменной, например
Result db 10 dup(?), '$'
Поменяйте
&quot писал(а):mov ax,@data
на mov ax, cs

Re: Обьясните плиз

Добавлено: 17 янв 2008, 18:00
Apokal
Зделал как вы говорили:
Вместо Result db '' написал Result db 10 dup(?) ----- в итоге на екран нечего не выводитса всмысле он пуст. :(

Зделал по коду airyashov все получилось. Но я немогу понять заечм он занес ax в es, ведь es это всего лиш дополнительный регистр и в дальнейшем он нигде неиспользуетса.