PDA

Просмотр полной версии : Обьясните плиз



Apokal
14.01.2008, 19:26
Здраствуйте!
Я недавно начал изучать Ассемблер и у меня возникло несколько вопросов и проблем при написании програмы. Пишу я на 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 чтобы я понял почему код неработает. Заранее спасибо.

somewhere
15.01.2008, 01:53
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

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 уже определена, рекомендуют добавить подчеркивание, или назвать по-другому

3. После того как я ассемблирую этот код ( при этом никаких ошыбок необнаружываетса ), я его соединяю с файлом obj но при этом тоже выдаетса ошыбка уже при линковке:
Test_1.obj : fatal error LNK 1190: invalid fixup found, type 0x0001
Данная ошибка мне не известна, она связана с неверным компоновочным модулем в объектом файле, что то видать не срослось между компилятором и линковщиком. Попробуйте поставить более свежий линковщик, который внятно поймет что там нацарапал этот ненавистный мною masm32

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

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


.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с --- но в итоге прога просто пропищала высветила шото непоянтное и сама закрылась недожыдаясь нажатия клавиш.


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

somewhere
16.01.2008, 09:50
№1. Насколько я понял две команды
mov ax,@data
mov ds,ax
это команды которые оределяют адрес сегмента кода. Обязательно ли их использывать? Просто я встречал код и без этих двух команд.
Читайте в книжках про PSP-сегменты, там вполне понятно написано какими значениями будут инициализированы сегментные регистры при запуске программы, если вы не уверены - запишите значения вручную.

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

№3
Главный вопрос:
В результате запуска програмы вместо цифры 2 выводиста всякий мусор и издаетса дикий писк Я так понимаю что неправильно перевел двоичное число в строку.
После последней команды Stosb, содержимое регистра DI указывает на первый байт после вашей строки. Затем вы подготавливаете параметры для вывода этой строки, но в регистре DX должно находиться смещение начала вашей строки а не конца. В результате выводиться то, что находиться после этой самой строки, а именно - ваш код, данные ОС и т.д., в которых по-любому где-то встречаеться символ с кодом 7, который для системы вывода означает команду выдать звуковой сигнал. Все это будет продолжаться до тек пор, пока не встретится символ "$".
№4
Я хотел чтобы програма завершалась путем нажатия клавиш Сtrl+Break для этого занес в al 01, а в ah 4с --- но в итоге прога просто пропищала высветила шото непоянтное и сама закрылась недожыдаясь нажатия клавиш.
А она и не должна ничего ждать, то что заноситься в AL будет доступно операционной системе как код ошибки, которую она может прочитать во внутренней переменной ERRORCODE и тем самым выполнять определенные действия. Читайте документацию к функциям MS-DOS и внимательно следите за содержимым регистров и все у вас получиться.

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

определяют адрес сегмента данных
по умолчанию при загрузке указывает на PSP
для программ типа COM инициализация требуется, так как вся программа 1 сегмент

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

Apokal
17.01.2008, 16:35
Спасибо что ответили.

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

airyashov
17.01.2008, 16:51
.model small
.stack 100h
.data
Number = 2
Result db ' ','$'
.code

_start:

mov ax,@data
mov ds,ax
mov es,ax
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

somewhere
17.01.2008, 16:51
Result db ''
Размер этой переменной равен 0, по сути ее адрес такой же, как и у первой команды. Задайте фиксированное значение переменной, например
Result db 10 dup(?), '$'
Поменяйте

mov ax,@data
на mov ax, cs

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

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

somewhere
17.01.2008, 18:34
Но я немогу понять заечм он занес ax в es, ведь es это всего лиш дополнительный регистр и в дальнейшем он нигде неиспользуетса.
Читайте описание инструкции stos. И вообще как вы ассемблер так изучаете, если не знаете как работает инструкция?

Вместо Result db '' написал Result db 10 dup(?) ----- в итоге на екран нечего не выводитса всмысле он пуст.
Это мне не о чем не говорит, поскольку я не вижу весь исходный код

Apokal
17.01.2008, 18:53
Спасибо всем я понял в чем дело было. Извините что задаю иногда вопросы ответ на которые могу найти сам внимательней прочитав, просто есть пока плохая привычка все недоконца дочитывать, но я думаю вскоре избавлюсь от нее.

airyashov
18.01.2008, 12:29
потому что у вас используется строковая команда stosb

Команда STOSB копирует байт, расположенный в AL,
в место памяти, на которое указывает ES:DI,
а также инкрементирует или декрементирует DI
(в зависимости от состояния признака направления DF),
чтобы подготовиться к копированию AL в следующий байт памяти.

Apokal
22.01.2008, 21:54
Помогите пожалуйста в таком вопросе:

Я написал програму которая выводит на экран число которое хранитса в Number'e (число может как одно- так и многозначным).Вот код:


;Вывод на экран числа которое задаетса в переменной Number
.186
.model tiny
.stack 100h
.data
Number = 39
Result db 3 dup(?),'$'
.code
_start:
mov ax,@data
mov ds,ax
mov es,ax
mov di,[offset Result+2]
mov dx,offset Result
mov ax,Number
;--------------------------------------------------------
labe1:
std
mov ch,10
div ch
add ah,'0' ; Этот блок перевода одного числа в его ASCII код
xchg al,ah
stosb
;--------------------------------------------------------
cmp ah,0 ; Этот блок проверяет равно ли частное 0 если да то выводит строку на
je _Exit ; экран и завершает работу програмы
;--------------------------------------------------------
xchg al,ah
cbw ;Этот блок обменивает обратно значениями регистры al и ah и
jmp labe1 ; повторяет блок перевода одного числа в его ASCII код
;---------------------------------------------------------
_Exit:
xor ax,ax
mov ah,09h
int 21h
mov ax,4c00h ; Этот блок для вывода на экран строки и завершения програмы
int 21h
end _start


Програма работает нормально, все отлично.
Но постает несколько вопросов:

№1.
Как заранее предусмотреть размер Result'a, просто я на основе этой програмы хочу написать прогу которая читает с экрана, а потом выводит на экран число и в таком случае я незнаю какого размера будет введное чило?
№2
Командой mov di,[offset Result+2] я перемистилса в конец Result'a ( несчитая символа $).Можно ли это зделать как-то более удобным способом, учитывая что я небуду знать размер Result'a?

airyashov
23.01.2008, 09:27
Обычно в таком случае на экран выводят число по цифрам или предварительно сохранять в стеке, а так как размер числа заранее известен байт- макс 3 символа, слово 5-ь и т.д.
mov ax,Number - максимум 5 цифр в 10-ой

BBB
23.01.2008, 13:19
Командой mov di,[offset Result+2] я перемистилса в конец Result'a ( несчитая символа $).Можно ли это зделать как-то более удобным способом, учитывая что я небуду знать размер Result'a?
Если все-таки, в таком виде, то встать на "доллар", а потом сделать шаг назад:



Result db 28 dup(?)
Dollar db '$'
.code
_start:
..................
mov dx, offset Dollar
dec dx

somewhere
23.01.2008, 19:56
BBB, а зачем так извращаться?
mov dx, offset Dollar - 1

Apokal
23.01.2008, 21:41
Пасиб за предыдущие ответы.
Пытаясь написать простенькую програму которая выводит на экран то, что юзер ввел столкнулса с проблемой --- прога выводит всякий мусор.
Вот код:

.186
.model small
.stack 100h
.data
Result db 10,9 dup(20h),'$'
.code
_start:

mov ax,@data
mov ds,ax
mov dx,offset Result


mov ah,0Ah
int 21h
mov dx,offset Result
add dx,2
mov ah,09h
int 21h

end _start

Вроде все правильно зделал, в чем может быть проблема незнаю(

airyashov
24.01.2008, 09:18
а где закончить программу? (Это про мусор)


mov ax,4c00h
int 21h

но и исправив так программу работать будет только в частном случае, курите управляющие символы 0Dh, а так же формат буфера для функции 0Ah dos

Apokal
28.01.2008, 20:44
Помогите опять плиз!

Уже чуть углубилса в изучение ассемблера и дошол до создания файлов. Вот код проги которая создает раздел (директорию):


model small
.stack 100h
.386
.data
msg1 db "Enter name of directory: $"
newst db 0dh,0ah,"$"
errmsg db "Input/output error! $"
inputstrmax db 0ffh
inputstrsize db ?
inputstr db 0ffh dup (?)
.code
_start:

printstr proc
mov ah,09h
int 21h
ret
printstr endp

readstr proc
lea dx,inputstrmax
mov ah,0ah
int 21h
movzx cx,inputstrsize
lea bx,inputstr
add bx,cx
mov byte ptr [bx],0
ret
readstr endp

lea dx,msg1
call printstr
call readstr
mov ah,039h
lea dx,inputstr
int 21h
jc _ioerror

jmp _wait

_ioerror:
lea dx,errmsg
call printstr

_wait:
mov ah,0
int 16h
mov ax,4c00h
int 21h
end _start

При запуске програмы начинает пищять и "матюкатса"((. Помогите плиз.

somewhere
28.01.2008, 23:38
программа начинается с метки _start, там же находится процедура printstr, а вот что находиться в тот момент в DX - никому не известно.

airyashov
29.01.2008, 08:47
точка входа мимо, попадаете сразу в процедуру в DX непонятно что, а потом по возврату ret

Apokal
30.01.2008, 21:46
Спасибо за ответы! Я понял в чем дело было. Я просто потом добавил переход на метку которая находитса уже за описаваемими процедурами. При дальнейшей работе с файлами у мен возник интересный вопрос. Вот код програмы которая создает директорию, переходит в нее, там создает новый файл. Но вопрос в том почему файл создаетса только в той папке которая была создана в папке с тасмом, еслия например создам папку просто на диске С то в той папке файл несоздадитса:D Обьясните плиз почему так?:confused:



model small
.386
.stack 100h
.data
msg1 db "Enter name of directory: $"
msg2 db "Directory created successful!",0dh,0ah,"$"
msg3 db "Enter name of file: $"
msg4 db "File created successful!",0dh,0ah,"$"
filehandle dw ?
newst db 0dh,0ah,"$"
errmsg db "Input/output error! $"
inputstrmax db 0ffh
inputstrsize db ?
inputstr db 0ffh dup (?)
.code
_start:
mov ax,@data
mov ds,ax

jmp _real_start

printstr proc
mov ah,09h
int 21h
ret
printstr endp

readstr proc
lea dx,inputstrmax
mov ah,0ah
int 21h
movzx cx,inputstrsize
lea bx,inputstr
add bx,cx
mov byte ptr [bx],0
ret
readstr endp

_real_start:
;-----------------------------Creating a new directory-------------------------
lea dx,msg1
call printstr
call readstr
mov ah,039h
lea dx,inputstr
int 21h
jc _ioerror
lea dx,newst
call printstr
lea dx,msg2
call printstr
;----------------------------Entering a new directory-------------------------------
mov ah,03bh
lea dx,inputstr
int 21h
jc _ioerror
;----------------------------Creating a new file with it's opening------------------
lea dx,msg3
call printstr
call readstr
mov ah,03ch
xor cx,cx
lea dx,inputstr
int 21h
jc _ioerror
lea dx,newst
call printstr
lea dx,msg4
call printstr
mov filehandle,ax
;---------------------------Closing a new file----------------------------------------
mov ah,03eh
mov bx,filehandle
int 21h

jmp _wait

_ioerror:
lea dx,newst
call printstr
lea dx,errmsg
call printstr

_wait:
mov ah,0
int 16h
mov ax,4c00h
int 21h
end _start

somewhere
30.01.2008, 23:03
Функция 3Bh - аналог команды ДОС ChDir или CD
Даже если в параметрах функции четко указан диск, который отличается от текщего, то текущий диск не меняется и переход в заданную директорию не выполняется.
Перед тем, как сменить текущую директорию - смените текущий диск на тот, который нужен.
А вообще использование смены текущего диска и папки для создания файла по заданному пути - дурной тон, т.к. всегда можно создать файл указав полный путь, не травмируя психику пользователя которому надо будет еще обратно идти. Туда, откуда его перекинули текущую папку

Apokal
08.03.2008, 12:23
Нужна ваша помощь.

Необходимо написать програму на ассемблере, которая показывала бы пинг аналогично до того как в командной строке когда пишем ping server adress.
Юзер вводит адрес серва а прога выводит пинг.
Подскажыте с алгоритмом решения, бо я в этом нешарю. Заранее спс.

airyashov
10.03.2008, 00:49
Под винду небось хотите или под ДОС?

Apokal
10.03.2008, 12:28
Под винду. Мне ненадо особой сложности -- бо мне будет трудно в реализации алгоритма на асме, так как ассемблер я на уровне нюба пока знаю.

somewhere
10.03.2008, 13:36
А какой тут может быть алгоритм, вся реализация-то через WinAPI идет. Просто тупо череда Call с параметрами через стек - вот вам и весь алгоритм.

Apokal
10.03.2008, 17:32
Тоесть через ассемблер никак нельзя?

Serge_Bliznykov
10.03.2008, 23:23
Тоесть через ассемблер никак нельзя?
блин, а если Вам в ДОС надо строчку на экран вывести - вы как, будет видеадаптер программировать или всё таки вызовите функцию 21 прерывания?!
Так и здесь - всё будет на ассемблере - просто заполните нужные параментры и вызовите функцию WinAPI - это и будет всё на ассемблере!!

Apokal
11.03.2008, 08:31
До меня дошло:D Спасибо за помошь.