I’m getting this error when I try to build this code:
1>------ Build started: Project: Project, Configuration: Debug Win32 ------
1> Assembling [Inputs]...
1>assign2.asm(12): error A2022: instruction operands must be the same size
1>assign2.asm(13): error A2022: instruction operands must be the same size
It happens when I try to subtract ml1337skillz
from usPop
and store that result into Difference
. I’m using eax
as a temporary register for it.
TITLE Learning (learning.asm)
INCLUDE Irvine32.inc
.data
usPop DWORD 313900000d ; 32-bit
my1337Sk1LLz WORD 1337h ; 16-bit
Difference SWORD ? ; 16-bit
.code
main PROC
FillRegs:
mov eax,usPop ;load 3139000000d into eax ; fine
sub eax,my1337Sk1LLz ;subtracts 1337h from usPop in eax ; error #1
mov Difference, eax ;stores eax into Difference ; error #2
call DumpRegs ;shows Registers
exit ;exits
main ENDP
END main
Peter Cordes
312k44 gold badges571 silver badges805 bronze badges
asked Apr 29, 2013 at 2:11
0
These two lines are your problem:
sub eax,my1337Sk1LLz ;subtracts 1337h from usPop in eax
mov Difference, eax ;stores eax into Difference
eax
is 32 bits, but both my1337Sk1LLz
and Difference
are 16 bits.
There are two ways you might get around this:
-
Changing the size of
my1337Sk1LLz
andDifference
. Right now you have the types asWORD
andSWORD
, respectively. You can change those toDWORD
andSDWORD
to make them 32-bit. -
Zero-extending and truncating. You’ll need another register. I’ll use
edx
since you don’t seem to be using it there. First, you’ll need to sign-extendmy1337Sk1LLz
:movzx edx, my1337Sk1LLz ; move, zero-extended, my1337Sk1LLz into EDX
Then you can do the subtraction:
sub eax, edx ; they're the same size now so we can do this
Then you can store the low word of
eax
intoDifference
, discarding the high word:mov Difference, ax
answered Apr 29, 2013 at 2:14
icktoofayicktoofay
125k21 gold badges246 silver badges230 bronze badges
5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
.686; Директива определения типа микропроцессора .Model flat, stdcall; задачи линейной модели памяти ; И соглашения ОС Windows option casemap: none; отличие малых и больших букв include masm32includewindows.inc include masm32includekernel32.inc include masm32includefpu.inc include masm32includeuser32.inc include masm32includemsvcrt.inc includelib masm32libuser32.lib includelib masm32libkernel32.lib includelib masm32libmsvcrt.lib includelib masm32libfpu.lib .Data; директива определения данных _c dd 24 sum dd 0 max dd 0; запись в 32-разрядную ячейку памяти с именем op1 temp dd 7 frmt db "% d", 0 buf db 50 dup (?) stdout DWORD ? stdin DWORD ? cRead dd ? mas1 dd 32 dup (0) nomer dd 0 st1 db "Vvesty masiv:" st2 db "Вывод результата перемещения", 0 st3 db 10 dup (0) ifmt db "Максимальный элемент =% d. Строка% d перенена в конец массива", 0 .Code; директива начала кода _start: lea esi, mas1; загрузки адреса начала массива mov ecx, _c m1: mov ebx, ecx invoke GetStdHandle, STD_OUTPUT_HANDLE mov stdout, eax invoke GetStdHandle, STD_INPUT_HANDLE mov stdin, eax invoke WriteConsoleA, stdout, ADDR st1, 14, NULL, NULL; VIVOD ST1 invoke ReadConsole, stdin, ADDR buf, 20, ADDR cRead, NULL; чтение числа как символ invoke crt_atoi, ADDR buf;превратить символ в число mov [esi], eax add esi, 4 mov ecx, ebx loop m1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov ecx, _c lea esi, mas1;загрузка адреса начала массива mov eax, [esi]; загрузки числа m3: .IF (eax > max); условие mov max, eax add esi, 4; расчет адреса нового числа mov eax, [esi] loop m3 .ELSE; иначе add esi, 4;расчет адреса нового числа mov eax,[esi] loop m3; перейти,если ecx и 0 .ENDIF; окончания директивы высокого уровня ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov ecx, _c lea esi, mas1; загрузки адреса начала массива mov eax, [esi]; загрузки числа m4: .IF (eax == max); условие inc nomer; находим в каком месте находится максимальный элемент add esi, 4;расчет адреса нового числа mov eax, [esi] jmp m5 loop m4 .ELSE; иначе inc nomer add esi, 4; расчет адреса нового числа mov eax, [esi] loop m4; перейти, если ecx и 0 .ENDIF; окончания директивы высокого уровня m5: mov eax,nomer mov edx,0 div temp; в регистре eax находится число строки - 1 mov edx,0 .IF (eax == 0); условие mov ebx,24 .ELSEIF (eax == 1); условие mov ebx,18 .ELSEIF (eax == 2); условие mov ebx,12 .ELSEIF (eax == 3); условие mov ebx,6 .ENDIF mov ecx,6 mov edx,ax shl edx,2 add ebx,edx x1: lea esi,mas1; загрузки адреса начала массива mov edx,[Esi + eax * 4]; загрузки числа mov [esi + ebx],edx mov edx,0 mov [esi],edx add esi,4 loop x1 jmp end_prog end_prog: mov ebx,max inc eax invoke wsprintf, ADDR st3, ADDR ifmt, ebx,ax invoke MessageBox, NULL, addr st3, addr st2, MB_OK invoke ExitProcess, 0 ret end _start; окончания программы |
-
Denis__
New Member
- Публикаций:
-
0
- Регистрация:
- 5 янв 2006
- Сообщения:
- 56
Fasm:
-
lea eax, [esi+caption-InjectCode]
-
lea eax, [esi+text-InjectCode]
-
call [esi+p_MessageBox-InjectCode]
Masm:
-
lea eax, [esi+(caption-InjectCode)]
-
lea eax, [esi+(text-InjectCode)]
-
call [esi+(p_MessageBox-InjectCode)] ;здесь компилятор выдает ошибку
Собственно как реализовать call [esi+p_MessageBox-InjectCode] в Masm, варианты типа:
-
lea eax, [esi+(p_MessageBox-InjectCode)]
не предлагать
-
В случае масма, p_MessageBox в экзешнике может оказаться где угодно. Поэтому (p_MessageBox-InjectCode) получается релокабельным, в отличие от фасма, где все метки фиксированные.
-
Nouzui
New Member
- Публикаций:
-
0
- Регистрация:
- 17 ноя 2006
- Сообщения:
- 856
call dword ptr [esi+(p_MessageBox-InjectCode)]
? -
Расставить dword ptr и offset не забывайте. Кстати, хоть бы ошибку привёл.
-
Denis__
New Member
- Публикаций:
-
0
- Регистрация:
- 5 янв 2006
- Сообщения:
- 56
Код на работе,завтра номер ошибки напишу
-
Denis__
New Member
- Публикаций:
-
0
- Регистрация:
- 5 янв 2006
- Сообщения:
- 56
Ошибка:
error A2023: instruction operand must have size — по русскому же написано
Решение нашел:-
call dword ptr [esi+(p_MessageBox-InjectCode)]
В общем, тем можно закрыть, просто за морочился на работе.
Всем спасибо.
Задание занести в переменные значения a1=12 a2=17 a3=19 c1=15 c2=26. Произвести некоторые операции и вывести в окне MessageBox значение находящееся в регистре ecx. Вот мой код:
.386
.model flat,stdcall
option casemap:none
include masm32includewindows.inc
include masm32includemasm32.inc
include masm32includekernel32.inc
include masm32includeuser32.inc
includelib masm32libmasm32.lib
includelib masm32libkernel32.lib
includelib masm32libuser32.lib
.data
hello db "Hello", 0
buffer db 128 dup(0)
format db '%d',0
result db 'ecx = %d and ebx = %d',0
a1 dw 12
a2 dw 17
a3 dw 19
c1 dw 15
c2 dw 26
.code
start:
; eax = (a2-a1)*a3 = 95
mov eax, [a2]
mov ecx, [a1]
sub eax, ecx
mov ecx, [a3]
mul ecx
; ecx = c1+c2 = 41
mov ebx, [c1]
mov ecx, [c2]
add ecx, ebx
; ebx = a1+a2 = 29
mov ebx, [a1]
mov edx, [a2]
add ebx, edx
; edx - shift arifm left a2 for 4
mov edx, [a2]
sal edx, 4
; while (ecx > -5){
; rcx -= 3
; if (ecx mod 2 != 0){
; ebx += eax
; }
; }
mov edi, eax
nwhile:
cmp ecx, -5
jnge afterwhile
sub ecx, 3
mov eax, ecx
mov edx, 2
div edx
cmp edx, 0
je afterif
add ebx, edi
afterif:
jmp nwhile
afterwhile:
invoke wsprintf, offset buffer, offset format, ecx, ebx
invoke MessageBoxA, NULL, offset buffer , ADDR hello , MB_OK
invoke ExitProcess, 0
end start
При попытке компиляции .obj файла выдает такое:
counter.asm(31) : error A2022: instruction operands must be the same size
counter.asm(32) : error A2022: instruction operands must be the same size
counter.asm(34) : error A2022: instruction operands must be the same size
counter.asm(39) : error A2022: instruction operands must be the same size
counter.asm(40) : error A2022: instruction operands must be the same size
counter.asm(45) : error A2022: instruction operands must be the same size
counter.asm(46) : error A2022: instruction operands must be the same size
counter.asm(51) : error A2022: instruction operands must be the same size
Очевидно, что ошибка в занесении значений переменных в регистры, но что делать я так и не поняла.
Содержание
- Обьясните плиз
- При попытке сложить 14 и 3.08 в место корректного ответа выдает буквы и заменяет некоторые символы. Как фиксить?
- Не получается взять символ из строки на FASM?
- При попытке сложить 14 и 3.08 в место корректного ответа выдает буквы и заменяет некоторые символы. Как фиксить?
Обьясните плиз
Здраствуйте!
Я недавно начал изучать Ассемблер и у меня возникло несколько вопросов и проблем при написании програмы. Пишу я на 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:masm32Test_1.asm
G:masm32Test_1.asm(7) : error A2022: instruction operands must be the same size
2. Если убрать символ нижнего подчеркивания перед start то выйдет ошыбка:
Assembling: G:masm32Test_1.asm
G:masm32Test_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 чтобы я понял почему код неработает. Заранее спасибо.
[quote=»Apokal»]1. В том виде котором я написал код он ассемблируетса нормально но как только я заменяю .186 на .386 тут же высвечиваетса ошыбка:
Assembling: G:masm32Test_1.asm
G:masm32Test_1.asm(7) : error A2022: instruction operands must be the same size[/quote]
Директива .386 подразумевает после себя 32-разрядные инструкции и адрессацию. Т.е. теперь смещения станут 32 битные, и команда должна выглядеть как
mov edx, offset message
[quote=»Apokal»]2. Если убрать символ нижнего подчеркивания перед start то выйдет ошыбка:
Assembling: G:masm32Test_1.asm
G:masm32Test_1.asm(10) : warning A4023: with /coff switch, leading underscore required for start address : start[/quote]
По-умолчанию константа/метка start уже определена, рекомендуют добавить подчеркивание, или назвать по-другому
[quote=»Apokal»]3. После того как я ассемблирую этот код ( при этом никаких ошыбок необнаружываетса ), я его соединяю с файлом obj но при этом тоже выдаетса ошыбка уже при линковке:
Test_1.obj : fatal error LNK 1190: invalid fixup found, type 0x0001[/quote]
Данная ошибка мне не известна, она связана с неверным компоновочным модулем в объектом файле, что то видать не срослось между компилятором и линковщиком. Попробуйте поставить более свежий линковщик, который внятно поймет что там нацарапал этот ненавистный мною masm32
Спасибо за ответ. Я поменял линковщик на более новый и теперь все работает.
Опять нужна ваша помощь!
Пытаюсь написать програму которая выводит на экран число.
Вот код:
[code]
.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
[/code]
Теперь мои вопросы:
№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с — но в итоге прога просто пропищала высветила шото непоянтное и сама закрылась недожыдаясь нажатия клавиш.
Помогите пожалуйста ещо раз!
[quote=»Apokal»]№1. Насколько я понял две команды
mov ax,@data
mov ds,ax
это команды которые оределяют адрес сегмента кода. Обязательно ли их использывать? Просто я встречал код и без этих двух команд.[/quote]
Читайте в книжках про PSP-сегменты, там вполне понятно написано какими значениями будут инициализированы сегментные регистры при запуске программы, если вы не уверены — запишите значения вручную.
[quote=»Apokal»]№2.
Правильно ли, что регистры SI и DI это регистры где хранятса смещение даных, которые должны быть перемещены (регистр SI) и смещение даных, куда должно будет шото помещено (регистр DI). Если это правильно то просто напишыте «Да». Я по этому определению и написал строку «mov di,offset Result» поскольку я буду в Result помещать другие данные.[/quote]
Значения регистров SI и DI как смещений операндов источника и приемника обязательы лишь при использовании строковых команд, таких как MOVS, SCAS, CMPS, STOS, INS и т.д. Если вы не используете эти команды, смещения операндов источника и назначения можете загружать в любой регистр, для которого допустима адресация в реальном режиме. В защищенном режиме можете использовать любой регистр общего назначения.
[quote=»Apokal»]№3
Главный вопрос:
В результате запуска програмы вместо цифры 2 выводиста всякий мусор и издаетса дикий писк Я так понимаю что неправильно перевел двоичное число в строку.[/quote]
После последней команды Stosb, содержимое регистра DI указывает на первый байт после вашей строки. Затем вы подготавливаете параметры для вывода этой строки, но в регистре DX должно находиться смещение начала вашей строки а не конца. В результате выводиться то, что находиться после этой самой строки, а именно — ваш код, данные ОС и т.д., в которых по-любому где-то встречаеться символ с кодом 7, который для системы вывода означает команду выдать звуковой сигнал. Все это будет продолжаться до тек пор, пока не встретится символ «$».[quote=»Apokal»]№4
Я хотел чтобы програма завершалась путем нажатия клавиш Сtrl+Break для этого занес в al 01, а в ah 4с — но в итоге прога просто пропищала высветила шото непоянтное и сама закрылась недожыдаясь нажатия клавиш.[/quote]
А она и не должна ничего ждать, то что заноситься в AL будет доступно операционной системе как код ошибки, которую она может прочитать во внутренней переменной ERRORCODE и тем самым выполнять определенные действия. Читайте документацию к функциям MS-DOS и внимательно следите за содержимым регистров и все у вас получиться.
[QUOTE=Apokal;48766]№1. Насколько я понял две команды
mov ax,@data
mov ds,ax
это команды которые оределяют адрес сегмента кода. Обязательно ли их использывать? Просто я встречал код и без этих двух команд.
[/QUOTE]
определяют адрес сегмента данных
по умолчанию при загрузке указывает на PSP
для программ типа COM инициализация требуется, так как вся программа 1 сегмент
при использовании строковых комант обратите внимание с каким сегментом работает приемник, т.е. с чем в паре работает DI
Но у меня опять нечего неполучилось хотя прогрес кое какой есть. В коде я заменил строку mov dx,di на mov dx,offset Result. Но на экране тот же результат хотя мусора и писка стало раза в 3 меньше. Я даже скачал СodeView и там проследил за всемя регистрами —— все происходило правильно и в конце в dx было смещение Result’a.
Единственное что, так это я незнаю как просмотреть содержимое Result’a. При попытке просмотреть в СodeView выдало сообщение:
«Expresion cannot be evaluated»
[CODE].model small
.stack 100h
.data
Number = 2
Result db ‘ ‘,’$’
.code
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
[quote=»Apokal»]Result db »[/quote]
Размер этой переменной равен 0, по сути ее адрес такой же, как и у первой команды. Задайте фиксированное значение переменной, например
Result db 10 dup(?), ‘$’
Поменяйте
[quote=»airyashov»]mov ax,@data[/quote]
на mov ax, cs
Зделал как вы говорили:
Вместо Result db » написал Result db 10 dup(?) —— в итоге на екран нечего не выводитса всмысле он пуст.:(
Зделал по коду airyashov все получилось. Но я немогу понять заечм он занес ax в es, ведь es это всего лиш дополнительный регистр и в дальнейшем он нигде неиспользуетса.
Источник
При попытке сложить 14 и 3.08 в место корректного ответа выдает буквы и заменяет некоторые символы. Как фиксить?
p.s. Если задать число и ответ будет меньше 10, то ответ дает нормально
- Вопрос задан более двух лет назад
- 100 просмотров
Простой 6 комментариев
Чего-то я совсем не понял. Вот так:
планировалось сложить именно два числа? Именно два числа 14 и 3.08?
Ну-ну, ну-ну. Числа из их ASCII представления надо бы сначала именно в числа преобразовать, это раз. И для вещественного сложения, а 3.08 именно вещественное число, целочисленные регистры какбе не используются.
biso, не по таблице ASCII, а просто перевести эти строки в понятные процессору числа, только тогда он будет их складывать. Ну и для вывода результата перевести его из числа обратно в строку.
Это очень большая, долгая и обширная тема, в паре-тройке, да даже в десятке сообщений на Q&A её не обсудить.
Что это за кошмар, вообще? Кто вас научил так строку в число конвертировать:
?
Да, оно сработает для одиночных цифр, для дву- и более значных будет полная ерунда (тут примерно написано почему).
Ну а float’ы складывать так же — это надо додуматься. Вы же знаете про существование FPU?
Источник
Не получается взять символ из строки на FASM?
Windows, FASM x86, exe
Есть структура PROCESSENTRY32, я её заполняю через Process32FirstProcess32Next, и мне нужно получить первый элемент из szExeFile.
Пробую так, но пишет «Operand size not specified»:
Что делать? Как быть?
- Вопрос задан более двух лет назад
- 279 просмотров
Видимо, мне нужно побольше узнать о функциях ассемблера, потому что я ограничиваюсь только lea, mov, jmp, jnz, je, jz, и др.
Про rep movsb , cld не знал, соответственно не смог выполнить это задание.
Этот кусок кода сдвигает строку влево на один символ, перемещая первый символ строки на место последнего. Чтобы не сдвигать завершающий строку нуль-терминатор, при определении strlen добавляем минус один. А в ECX помещаем еще на единицу меньше, так как один символ будет обработан отдельно через регистр AL. В приемник загружаем адрес начала строки, а в источник — адрес второго символа (stroka+1). Перед запуском копирования цепочки байтов сохраняем первый символ в AL. После копирования извлекаем его по адресу, содержащемуся в EDI, — это будет уже адрес последнего символа строки
Вот вариант полегче:
Это я уже сам додумал.
В общем обрезаем всё до нужного символа, потом сохраняем один символ в al, а потом из al в eax.
К примеру, есть str db ‘abc’
В lea eax, [text+0] мы обрезаем его до 0 элемента — «abc»
Далее в mov byte al, [eax] мы из eax сохраняем только один байт в al, полчаем ‘a’
И возвращаем его в eax mov byte [eax], al
Готово. Мы взяли 1 символ из строки. Тем самым если вместо 0 поставим 1 то возьмём второй символ, и т.д.
Источник
При попытке сложить 14 и 3.08 в место корректного ответа выдает буквы и заменяет некоторые символы. Как фиксить?
p.s. Если задать число и ответ будет меньше 10, то ответ дает нормально
- Вопрос задан более двух лет назад
- 100 просмотров
Простой 6 комментариев
Чего-то я совсем не понял. Вот так:
планировалось сложить именно два числа? Именно два числа 14 и 3.08?
Ну-ну, ну-ну. Числа из их ASCII представления надо бы сначала именно в числа преобразовать, это раз. И для вещественного сложения, а 3.08 именно вещественное число, целочисленные регистры какбе не используются.
biso, не по таблице ASCII, а просто перевести эти строки в понятные процессору числа, только тогда он будет их складывать. Ну и для вывода результата перевести его из числа обратно в строку.
Это очень большая, долгая и обширная тема, в паре-тройке, да даже в десятке сообщений на Q&A её не обсудить.
Что это за кошмар, вообще? Кто вас научил так строку в число конвертировать:
?
Да, оно сработает для одиночных цифр, для дву- и более значных будет полная ерунда (тут примерно написано почему).
Ну а float’ы складывать так же — это надо додуматься. Вы же знаете про существование FPU?
Источник