Доброе время суток! Скажу срузу: я начал изучать язык ассемблера позавчера. Так что, не судите строго )) Вобщем есть задача: сложить два 80ти битных числа. Я понимаю, что на эту тему скорее всего уже написано много, однако мне щас нужно немножко доходчивых объяснений вместо многих мегабайт текста. Вобщем взял я для своей задачи пример из Зубкова и переделал его следующим образом: Код (Text): ; .model tiny .code .386 org 100h ; начало COM-файла start: ;выдача сообщения mess1 mov ah,9 mov dx,offset mess1 int 21h mov dx,offset crlf mov ah,9 int 21h mov eax,dword ptr bigval_1[16] add eax,dword ptr bigval_2[16] mov dword ptr bigval_3[16],eax mov eax,dword ptr bigval_1[12] adc eax,dword ptr bigval_2[12] mov dword ptr bigval_3[12],eax mov eax,dword ptr bigval_1[8] adc eax,dword ptr bigval_2[8] mov dword ptr bigval_3[8],eax mov eax,dword ptr bigval_1[4] adc eax,dword ptr bigval_2[4] mov dword ptr bigval_3[4],eax mov eax,dword ptr bigval_1 adc eax,dword ptr bigval_2 mov dword ptr bigval_3,eax ;печать результата call print mov eax,dword ptr bigval_3[4] call print mov eax,dword ptr bigval_3[8] call print mov eax,dword ptr bigval_3[12] call print mov eax,dword ptr bigval_3[16] call print mov dx,offset crlf mov ah,9 int 21h ret mess1 db 'REZULTAT = $' crlf db 0Dh,0Ah,'$' bigval_1 dd 0FF00h,0FF00h,0FF00h,0FF00h,0FF00h bigval_2 dd 0FFh,0FFh,0FFh,0FFh,0FFh bigval_3 dd 0h,0h,0h,0h,0h ; процедура побайтной выдачи содержимого регистра ЕАХ print: mov esi,eax shr eax,24 call print_al mov eax,esi shr eax,16 call print_al mov eax,esi shr eax,8 call print_al mov eax,esi call print_al ret ; процедура print_al ; выводит на экран число в регистре AL в шестнадцатеричном формате print_al: mov dh,al and dh,0Fh shr al,4 call print_nibble mov al,dh ; процедура вывода 4 бит (шестнадцатеричной цифры) print_nibble: cmp al,10 sbb al,69h das mov dl,al mov ah,2 int 21h ret end start Результатом такой программы будет: Код (Text): REZULTAT = 0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF Однако,если я все правильно понимаю, то это число не 80-ти, а 160-ти битное: Код (Text): FFFFh = 1111 1111 1111 1111b Т.е. я ожидаю результат: Код (Text): FFFFFFFFFFFFFFFFFFFF Я написал вместо Код (Text): bigval_1 dd 0FF00h,0FF00h,0FF00h,0FF00h,0FF bigval_2 dd 0FFh,0FFh,0FFh,0FFh,0FFh bigval_3 dd 0h,0h,0h,0h,0h вот так: Код (Text): bigval_1 dw 0FF00h,0FF00h,0FF00h,0FF00h,0FF bigval_2 dw 0FFh,0FFh,0FFh,0FFh,0FFh bigval_3 dw 0h,0h,0h,0h,0h Но тогда в результате будет: Код (Text): 000100000100000100000100000100 Вобщем мне кажется, что я не знаю каких-то основ, и понимаю все неправильно. Покажите плиз где затык и объясните,как нужно правильно. Только не нужно пожалуйста посылать в гугл. Мне нужна сейчас не информация, а простое и доходчивое объяснение что бы разобраться в самаом простом. Заранее благодарен.
Хм... по-моему, 80 бит = 10 байт, а вы складываете ячейки из двадцатибайтного диапазона... Код (Text): mov eax, dword ptr bigval_1 add eax, dword ptr bigval_2 mov dword ptr bigval_3, eax mov eax, dword ptr bigval_1[4], eax adc eax, dword ptr bigval_2[4], eax mov dword ptr bigval_3[4], eax mov ax, word ptr bigval_1[8] adc ax, word ptr bigval_2[8] mov word ptr bigval_3[8], ax <...> bigval_1 dw 0FF00h, 0FF00h, 0FF00h, 0FF00h, 0FF00h bigval_2 dw 0FFh, 0FFh, 0FFh, 0FFh, 0FFh bigval_3 dw 5 dup (0)
Спасибо за ответ. Попробовал. Получился такой код: Код (Text): .model tiny .code .386 org 100h ; начало COM-файла start: ;выдача сообщения mess1 mov ah,9 mov dx,offset mess1 int 21h mov dx,offset crlf mov ah,9 int 21h mov eax,dword ptr bigval_1 add eax,dword ptr bigval_2 mov dword ptr bigval_3[8],eax mov eax,dword ptr bigval_1[4] adc eax,dword ptr bigval_2[4] mov dword ptr bigval_3[4],eax mov ax,word ptr bigval_1[8] adc ax,word ptr bigval_2[8] mov word ptr bigval_3,eax[8] ;печать результата call print mov eax,dword ptr bigval_3[4] call print mov eax,dword ptr bigval_3[8] call print mov dx,offset crlf mov ah,9 int 21h ; перевод строки ret mess1 db 'REZULTAT = $' crlf db 0Dh,0Ah,'$' bigval_1 dw 0FF00h,0FF00h,0FF00h,0FF00h,0FF00h bigval_2 dw 0FFh,0FFh,0FFh,0FFh,0FFh bigval_3 dw 5 dup (0) ; процедура побайтной выдачи содержимого регистра ЕАХ print: mov esi,eax shr eax,24 call print_al mov eax,esi shr eax,16 call print_al mov eax,esi shr eax,8 call print_al mov eax,esi call print_al ret ; процедура print_al ; выводит на экран число в регистре AL в шестнадцатеричном формате print_al: mov dh,al and dh,0Fh ; DH - младшие 4 бита shr al,4 ; AL - старшие (shr - логический сдвиг вправо) call print_nibble ; вывести старшую цифру mov al,dh ; теперь AL содержит младшие 4 бита ; процедура вывода 4 бит (шестнадцатеричной цифры) print_nibble: cmp al,10 ; три команды, переводящие цифру в AL sbb al,69h ; в соответствующий ASCII-код das ; (см. описание команды DAS) mov dl,al ; код символа - в DL mov ah,2 ; номер функции DOS в AH (вывод символа) int 21h ; вызов функции ret ; возврат из процедуры end start В результате при компиляции получаю ошибку: Код (Text): error A4910: cannot open file: L:\masm\work\ML.err bigval.asm(26) : error A2032: И почему здесь Код (Text): mov eax,dword ptr bigval_1 add eax,dword ptr bigval_2 mov dword ptr bigval_3[8],eax mov eax,dword ptr bigval_1[4] adc eax,dword ptr bigval_2[4] mov dword ptr bigval_3[4],eax mov ax,word ptr bigval_1[8] adc ax,word ptr bigval_2[8] mov word ptr bigval_3,eax[8] мы выполняем только три раза сложение, в то время как нужно (если я правильно понимаю) сложить 5 двойных слов Код (Text): bigval_1 dw 0FF00h,0FF00h,0FF00h,0FF00h,0FF00h bigval_2 dw 0FFh,0FFh,0FFh,0FFh,0FFh bigval_3 dw 5 dup (0) Я знаком с ассемблером только 3й день! Объясните пожалуйста все доходчиво и подробно. Спасибо.
80 бит = 10 байт = 5 слов, в то время, как 5 двойных слов = 10 слов = 20 байт = 160 бит. Так что число хранится в десяти байтах, т.е. 2,5 двойных словах. Вот и получается, что младшие 64 бита складываются по двойным словам, а довески 16битные - как слова. Код (Text): mov eax,dword ptr bigval_1 ;складываем младшие 32 бита add eax,dword ptr bigval_2 mov dword ptr bigval_3,eax ;; здесь не [8] mov eax,dword ptr bigval_1[4] ; "средние" 32 бита adc eax,dword ptr bigval_2[4] mov dword ptr bigval_3[4],eax mov ax,word ptr bigval_1[8] ; оставшиеся 16 бит adc ax,word ptr bigval_2[8] mov word ptr bigval_3[8],ax;;здесь 16битный mov
Спасибо, JAPH, немножко разобрался. Теперь вроде бы все работает. Только теперь бы еще разобраться вот с чем: моя программа теперь выглядит вот так Код (Text): .model tiny .code .386 org 100h ; начало COM-файла start: ;выдача сообщения mess1 mov ah,9 mov dx,offset mess1 int 21h mov dx,offset crlf mov ah,9 int 21h ;расчет mov eax,dword ptr bigval_1 add eax,dword ptr bigval_2 mov dword ptr bigval_3,eax mov eax,dword ptr bigval_1[4] adc eax,dword ptr bigval_2[4] mov dword ptr bigval_3[4],eax mov ax,word ptr bigval_1[8] adc ax,word ptr bigval_2[8] mov word ptr bigval_3[8],ax ;печать результата call print mov eax,dword ptr bigval_3[4] call print mov ax,word ptr bigval_3[8] call print mov dx,offset crlf mov ah,9 int 21h ; перевод строки ret mess1 db 'REZULTAT = $' crlf db 0Dh,0Ah,'$' bigval_1 dw 1Ah,1Ah,1Ah,1Ah,1Ah bigval_2 dw 6h,6h,6h,6h,6h bigval_3 dw 5 dup (0) ; процедура побайтной выдачи содержимого регистра ЕАХ print: mov esi,eax shr eax,24 call print_al mov eax,esi shr eax,16 call print_al mov eax,esi shr eax,8 call print_al mov eax,esi call print_al ret ; процедура print_al ; выводит на экран число в регистре AL в шестнадцатеричном формате print_al: mov dh,al and dh,0Fh ; DH - младшие 4 бита shr al,4 ; AL - старшие (shr - логический сдвиг вправо) call print_nibble ; вывести старшую цифру mov al,dh ; теперь AL содержит младшие 4 бита ; процедура вывода 4 бит (шестнадцатеричной цифры) print_nibble: cmp al,10 ; три команды, переводящие цифру в AL sbb al,69h ; в соответствующий ASCII-код das ; (см. описание команды DAS) mov dl,al ; код символа - в DL mov ah,2 ; номер функции DOS в AH (вывод символа) int 21h ; вызов функции ret ; возврат из процедуры end start и в результате её выполнения я получаю такой результат Код (Text): 002000200020002000200020 Т.е. последние 4 цифры (0020) как бы лишние (правильно?). Я думал,что нужно в этом месте поиграться Код (Text): call print mov eax,dword ptr bigval_3[4] call print mov ax,word ptr bigval_3[8] call print но как не пытался получается какая-то ерунда. Где и что я опять прошляпил? Еще раз спасибо.
Для начала, вы выводите не в том порядке. Чем старше разряды, тем больше номер байта, в котором он хранится. Вывод надо начинать со старших разрядов, т.е. с bigval_3[8], затем bigval_3[4] и bigval_3[0]. Но вот в bgival_3[8] надо вывести только слово (вы ведь так и пишете - mov ax, bigval_3[8]), а процедура print выводит двойное слово, вот и получается, что она показывает мусор из старших бит eax. Код (Text): mov al, bigval_3[9] call print_al mov al, bigval_3[8] call print_al mov eax, bigval_3[4] call print mov eax, bigval_3 call print
Большое спасибо! Почти во всем разобрался и программа работет правильно. Вот так у меня получилось в окончатеьном варианте: Код (Text): mov ax,word ptr bigval_3[9] call print_al mov ax,word ptr bigval_3[8] call print_al mov eax,dword ptr bigval_3[4] call print mov eax,dword ptr bigval_3 call print Только ещё один маленький вопрос просто для понимания: в этих двух числах Код (Text): bigval_1 dw 1Ah,1Ah,1Ah,1Ah,0DFh bigval_2 dw 6h,6h,6h,6h,20h старшинство разрядов слева направо или справа налево? Или это зависит от того,в каком порядке их обрабатывать? Иными словами, при сложении этих чисел мы ожидаем результат Код (Text): 00FF0020002000200020 или 002000200020002000FF Еще раз большое спасибо.
По-моему, как раз-таки Little-Endian отвечает за старший байт по старшему адресу. Такая придирка - зачем записывать слово bigval_3[9], если реально используется только байт?
tibibo тогда логичнее, чтоб не путать того, кто потом разбирать исходник будет : Код (Text): mov al,word ptr bigval_3[9] call print_al mov al,word ptr bigval_3[8] call print_al А вот так оптимальнее, т.к. каждый вызов принт - дорогой Код (Text): xor eax,eax mov ax,word ptr bigval_3[8] call print Но будут лишние нули при выводе.
wsd JAPH Поправьте меня,если я ошибаюсь, но по-моему JAPH прав: LittleEndian отвечает за старший байт по старшему адресу http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index.jsp?topic=/com.ibm.aix.pli.doc/lsh-bigendian.htm JAPH да,ошибка. Спасибо, что заметили. Я исправил на: Код (Text): mov al,byte ptr bigval_3[9] call print_al mov al,byte ptr bigval_3[8] call print_al valterg Спасибо за ответ, конечно вы правы. Но скорее всего вы имели в виду Код (Text): mov al,[b]BYTE[/b] ptr bigval_3 вместо mov al,[b]WORD[/b] ptr bigval_3 Иначе при компиляции получается ошибка Код (Text): bigval.asm(25): error A2070: bigval.asm(27): error A2070:
tibibo по смысловой нагрузке слов BigEndian - больший заканчивающий очевидней. по мануалам, да, ты прав - наоборот LittleEndian