Содержание
- ASM Community
- ASM Community
- ASM Community
- Перемещение регистра в индекс массива на ассемблере x86
- 2 ответы
- Masm выдает ошибку
Using masm I have the following code which works:
This compiles fine and works as excepted. Now I do the same thing just with sub instruction instead:
This gives the error: A2101: cannot add two relocatable labels.
Then I try also with xor:
which gives the error: A2026: constant expected.
Is there a way to fix it or won’t it be possible to get working? I find it strange that subtracting of labels seems to work while adding doesn’t.
Since the offset of your labels are not known at assembletime and can change at runtime (due to relocations) the values of label1 and label2 are not constant so only their relative difference can be calculated (with the subtract)
The only way to do this easily will be to resolve the offsets at runtime:
sub dword ptr , label1 + label2
xor dword ptr , label1 XOR label2
Thanks for the explanation.
The offset directive didn’t help either but thats understandable now.
I wonder if there is a document explaining those pre-processor directives like +, -, XOR and whatever else exists which is processed at compile time and not runtime.
It’s important to know what instructions are possible, then you know that all those calculations must take place at assemble-time because the instruction generated by the assembler is: sub , . And then the loader can relocate the constant — add the start memory address.
So, a relocatable address can be looked at as: +
is the same for the whole PE file.
Therefore, add dword ptr , label1 — label2
becomes: add dword ptr , + — ( + )
reduces to: add dword ptr , —
but: sub dword ptr , label1 + label2
becomes: sub dword ptr , + + +
reducing to: sub dword ptr , + + 2*( )
You can see now there is no way to calculate 2*( ) until run-time — unless you assume your program is going to load at 400000h, but the assembler has no way to know this.
With sub instruction I solved it now.
Maybe not perfect but it works:
sub dword ptr , 0 — (label1 — label2)
This gives the correct values and works as expected.
ups yeah :stupid:
/me goes tell himself not to code when brain is inactive
Источник
I’m working on a project for school and can’t seem to get past this one particular error.
The code that I have so far isn’t finalized and most likely has some logic errors that I will need to change, but for now I’m just trying to get it to compile.
I’ve posted the ASM code here:
http://kyleabaker.pastebin.com/m4236f1a1
I’m getting this error for the following lines (all the same error/problem): 86, 88, 90, 92, 97, 103, 110, 118, 122, 132, 134, 135, 137, 139, 141, 154
If I could understand how to fix one of them then I’m sure I could apply it to the rest.
Basically, I have an array with roman numerals that I’m attempting to access dynamically. I can access it using nextchar(0), I can’t use a variable in place of the 0 and that’s what I need. Is there any way I can work around this?
I feel like I’ve exhausted Google with a little information, but no direction. Thanks in advanced.
Edit:
I’m using DOSBox and Masm to compile (for my class).
When in doubt, RTFM. This maxim will never fail or rust.
MASM interprets label1(label2) as label1+label2, not as a subscript operator. As both of labels are relocatable (not constant), this arithmetic is not possible. Besides, such addressing mode does not exist in x86 architecture, you’ll need registers for indexed access.
Intel SDM and AMD ARM are freely available. They aren’t too hard to comprehend and contain vast amounts of information about architecture you’re trying to learn and write programs for.
I’ve been reading up a lot at http://www.emu8086.com/ with no luck so far.
If label1(label2) is interpreted as label1+label2, would I be able to do something like the following with the result that I expect from label1(label2)?
. or is the logic behind that going to be interpreted differently than just selecting the nth item in label1’s list?
No, that won’t work either. and isn’t what you want to do. As Balrd says, you need to use a register as an index. You’ve got, for example:
cmp nextchar(currchar), 20h
«currchar» is a variable, too, and you want to use its «», not its address (offset) as an index. If «currchar» were a word-sized variable, we could just do:
mov bx, currchar ; «» for Nasm — «», not offset!
But it’s a byte, so we have to do:
mov bh, 0
mov bl, currchar
cmp nextchar, 20h
Will do what you want (I think). As you see, there are a lot of instances that will have to be fixed.
(if you’re using Masm, why are you reading about emu8086?)
Источник
I’m doing my homework in univ.
but I have problems in my source.
like this.
1>D:9210039proj1.asm(49) : error A2101:cannot add two relocatable labels
1>D:9210039proj1.asm(51) : error A2101:cannot add two relocatable labels
please help me..
I emphasized 49,51 line in my source
my source is
N TEXTEQU ;the number of random numbers.
.data
string1 BYTE
string2 BYTE «ascending ordered numbers»,0dh,0ah,0
string3 BYTE «sum of numbers»,0dh,0ah,0
total_num DWORD 0
numbers WORD N dup(0)
temp DWORD 0
count DWORD ?
random_num DWORD ?
mov ecx,N
mov esi,0
random_generator:
call random32
mov random_num,eax
mov ax,WORD PTR random_num
mov numbers,ax
mov edx,OFFSET string1
call WriteString
MOVZX eax,numbers
call WriteHex
inc esi
loop random_generator
mov eax,0
mov ecx,N
mov esi,0
a:
mov count,ecx
mov ax,numbers
mov temp,esi
inc esi
sub ecx,esi
dec esi
b:
inc temp
CMP ax,numbers
jl not_condition
CMPXCHG numbers,ax
not_condition:
loop b
mov numbers,ax
inc esi
mov ecx,count
loop a
mov ecx,N
mov esi,0
mov edx,OFFSET string2
call WriteString
print_numbers :
MOVZX eax,numbers
add total_num,eax
call WriteDec
inc esi
loop print_numbers
mov edx,OFFSET string3
call WriteString
mov eax,total_num
call WriteDec
exit
main ENDP
END main
wiiji,
[] in MASM is a shortcut of +. I understood that you’re trying to index numbers array with temp variable value, this addressing mode is not supported by x86 (hint: register value can be used as index, and unlike C you have to scale it explicitly).
By the way, do you understand what cmpxchg does?
Источник
Перемещение регистра в индекс массива на ассемблере x86
я пытаюсь переместить bl зарегистрируйтесь в массив байтов на языке ассемблера x86, но следующий оператор выдает сообщение об ошибке от ассемблера masm.
mov arr[2], bl производит вывод 1>p4.asm(48): error A2101: cannot add two relocatable labels .
Можно ли переместить регистр в массив на ассемблере x86?
задан 26 марта ’13, 10:03
Я провел несколько дней в поисках ответа на этот вопрос, но ответов пока не нашел. — Anderson Green
bx это 16-битный регистр, который больше байта, если вам нужен только байт, содержащийся в bx , вам нужен доступ bl его нижняя 8-битная часть — Seki
@Seki Сейчас я исправил эту часть, но я все еще пытаюсь выяснить, как переместить регистр в определенный индекс массива. — Anderson Green
2 ответы
В основном то, что следующее должно работать для жестко закодированного значения индекса:
Для более общего способа:
ответ дан 26 апр.
mov byte ptr [ax], bl выдает эту ошибку: 1>p4.asm(54): error A2031: must be index or base register — Андерсон Грин
извините, хотя я могу довольно легко читать ассемблер, я немного заржавел, чтобы писать что-то самому. Я забываю, что mov byte ptr должен использовать базовый (bx/bp) или индексный (si/di) регистр. Смотрите мое обновление. — Секи
Если мы используем инструкцию с непосредственным операндом, то мы должны указать, сколько байтов получит наш операнд. Поэтому мы должны использовать такое ключевое слово, как байт, слово или DWORD чтобы сообщить ассемблеру, сколько следующих байтов местоположения оперативной памяти мы хотим получить.
Но если мы используем регистр в качестве операнда (при этом он известен среди байтов), то нам не нужно его указывать (для того, чтобы листинг стал меньше с более легким обзором).
Исключение с MASM и с регистром DWORD в качестве операнда.
Источник
Masm выдает ошибку
Я написал программу на MASM32, которая выдает ошибку, но я не вижу способа ее исправить. Программа должна заменить все элементы (символы), встречающиеся после последнего появления «a» на «*» во входной строке, которая вводится с клавиатуры; длина входной строки не превышает 100 символов.
Потому что вы не можете делать такие вещи, как buff1 [size1] , когда size и buff1 являются лейблами. Вы берете две перемещаемые метки и пытаетесь сложить их вместе. Вам нужно будет переместить значение, расположенное в size1 , в регистр, а затем использовать этот регистр в квадратных скобках.
как это? mov eax, [size1] push buff1 [eax]
(извините, неправильно прочитал вопрос, я думаю, что это действительно так): Инструкция цикла уменьшает ecx перед проверкой условия. В вашем коде вы никогда не устанавливаете длину строки (bigStr + 0, smallStr + 0), поэтому ecx изначально равен 0. Таким образом, ваша программа попытается обработать 2 ^ 32 символа, прежде чем цикл остановит ее.
Если вы используете цикл, вы должны сначала проверить предварительное условие, как в:
Я не понимаю что вы предлагаете делать
В вашем коде от @ cyc1 до цикла в качестве длины используется слово, хранящееся по смещению 0 вашей строки. Он инициализируется нулем и никогда не устанавливается. Таким образом, ecx будет равен нулю, поэтому инструкция цикла будет интерпретировать это как 2 ^ 32 итераций.
Как это исправить? я не понимаю
Похоже, вы пытаетесь назначить это с помощью pop [BigStr] [BigStr + 4] — это недопустимый синтаксис сборки, для этого вам нужно использовать две всплывающие инструкции. Я предполагаю, что проблема заключается в том, что вы пытаетесь протолкнуть два элемента; Intel Push этого не делает.
Источник
ut2010 1 / 1 / 1 Регистрация: 24.06.2012 Сообщений: 18 |
||||
1 |
||||
04.01.2013, 20:34. Показов 1743. Ответов 1 Метки нет (Все метки)
Приведенный код это часть большей задачи.
__________________
0 |
Mikl___ Ушел с форума 15703 / 7377 / 980 Регистрация: 11.11.2010 Сообщений: 13,321 |
||||
04.01.2013, 20:42 |
2 |
|||
ut2010,
1 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
04.01.2013, 20:42 |
2 |
-
wsd
New Member
- Публикаций:
-
0
- Регистрация:
- 8 авг 2007
- Сообщения:
- 2.824
Привет.
-
rasCon RASCONN 10 dup(<?>)
-
mov eax, offset rasCon[dNumber].szEntryName
-
invoke SendMessage, ebx,LB_ADDSTRING ,0 , eax
В MASM32
Даёт
error A2101: cannot add two relocatable labels
Где я напортачил? -
MSoft
New Member
- Публикаций:
-
0
- Регистрация:
- 16 дек 2006
- Сообщения:
- 2.854
скорее всего это не понравилось:
-
mov eax, offset rasCon[dNumber].szEntryName
попробуй сделать это в 2 действия через регистр
-
wsd
New Member
- Публикаций:
-
0
- Регистрация:
- 8 авг 2007
- Сообщения:
- 2.824
не помогает…
lea eax, rasCon[dNumber]
lea eax, [eax].RASCONN.szEntryNameни так
mov eax, offset rasCon[dNumber]
lea eax, [eax].RASCONN.szEntryName -
MSoft
New Member
- Публикаций:
-
0
- Регистрация:
- 16 дек 2006
- Сообщения:
- 2.854
я имел ввиду:
mov eax,dNumber
imul eax,eax,SizeOf RASCONN
lea eax,[eax].RASCON.szEntryName -
wsd
New Member
- Публикаций:
-
0
- Регистрация:
- 8 авг 2007
- Сообщения:
- 2.824
-
wsd
New Member
- Публикаций:
-
0
- Регистрация:
- 8 авг 2007
- Сообщения:
- 2.824
MSoft
Там кстати это ещё добавить надо…add eax, offset rasCon
Спасибо.
P.S. я ещё там зачем-то mov ebx, hListBox1 в цикл запихнул
I’ve written a program on MASM32 which throws an error, but I see no way to correct it. The program is to replace all elements (symbols) met after the last occurrence of ‘a’ to ‘*’ in input string, which is entered from the keybord; the input string is no longer than 100 symbols.
The error is following:
C:UsersMikolaAppDataLocalTempSASMprogram.asm(60) : error A2101: cannot add two relocatable labels
Here’s the code
.686P
.model flat, stdcall
option casemap: none
include c:masm32includewindows.inc
include c:masm32includeuser32.inc
include c:masm32includekernel32.inc
include c:masm32includemasm32.inc
includelib c:masm32libuser32.lib
includelib c:masm32libkernel32.lib
includelib c:masm32libmasm32.lib
.data
mes1 db 'String(1): '
mes2 db 'String(2): '
mes3 db 'Result...: '
len dd $ - mes3
crlf db 13,10
buff1 db 100 dup(0)
buff2 db 100 dup(0)
size1 dd 0
size2 dd 0
bigStr dd 0,0
smallStr dd 0,0
.code
start:
;------ Запрос и вводим строки
invoke WriteConsoleA, 7, mes1, [len], 0,0
invoke ReadConsoleA, 3, buff1, 100, size1,0
invoke WriteConsoleA, 7, mes2, [len], 0,0
invoke ReadConsoleA, 3, buff2, 100, size2,0
;------ Сравниваем размеры введённых строк
push buff1 [size1]
push buff2 [size2]
mov eax,[size1]
cmp eax,[size2]
jb @@small
pop [smallStr] [smallStr+4]
pop [bigStr] [bigStr+4]
jmp @@big
@@small: pop [bigStr] [bigStr+4]
pop [smallStr] [smallStr+4]
;------ Обработка длинной строки (меняем все/строчные на (N mod 10))
@@big: mov ecx,[bigStr]
mov esi,[bigStr+4]
mov edi,esi
xor ebx,ebx
@@cyc1: lodsb
inc bl
cmp al,'a'
jb @@next1
cmp al,'z'
ja @@next1
mov al,bl
aam
@@next1: stosb
loop @@cyc1
;------ Обработка короткой строки (после последнего 'a', все на '*')
mov ecx,[smallStr]
dec cx
push ecx
mov edi,[smallStr+4]
add edi,ecx
mov al,'a'
std
@@cyc2: repne scasb
cld
pop eax
or ecx,ecx
jz @@stop
xchg ecx,eax
sub ecx,eax
add edi,2
mov al,'*'
rep stosb
;------ Вывод результата из буфера
@@stop: invoke WriteConsoleA, 7, mes3, [len], 0,0
invoke WriteConsoleA, 7, buff1,[size1], 0,0
invoke WriteConsoleA, 7, crlf,2,0,0
invoke WriteConsoleA, 7, mes3, [len], 0,0
invoke WriteConsoleA, 7, buff2,[size2], 0,0
jmp $
@@exit: invoke ExitProcess, 0
end start
#arrays #assembly #character #x86-64 #masm
#массивы #сборка #характер #x86-64 #masm
Вопрос:
Я читал похожие сообщения по этому вопросу, но просто не могу найти ничего, что помогло бы мне решить мою проблему. По сути, я хочу изменить запись в массиве символов в определенной точке, поэтому просто индексирую ее. Я знаю, как это сделать с помощью магического числа (т.Е. Просто помещая в буфер [2] или что-то в этом роде), но я получаю ошибки, когда пытаюсь проиндексировать массив символов числовым значением, хранящимся в регистре или QWORD.
Итак, у меня есть массив символов, называемый buffer
buffer BYTE 4097 DUP (0)
и у меня также есть QWORD с именем parseNum
parseNum QWORD 0
Вот раздел кода, который вызывает у меня проблемы:
testJmp:
mov rbx, parseNum
xor buffer[rbx], 2
add parseNum, 2
cmp parseNum, 4097
jne testJmp
Предполагается, что этот код перебирает массив символов и применяет операнд XOR к каждой записи. Однако я могу это сделать, только если я могу индексировать значение, которое изменяется с каждым циклом. Когда я пытаюсь просто использовать xor buffer[parseNum], 2
, я получаю сообщение об ошибке, которое читается error A2101: cannot add two relocatable labels
в этой строке кода. Когда я пытаюсь переместить parseNum в rbx, а затем ввести rbx в качестве индекса, я также получаю сообщение об ошибке следующего содержания: error LNK2017: 'ADDR32' relocation to 'buffer' invalid without /LARGEADDRESSAWARE:NO
. Я в полной растерянности и полностью застрял. Надеюсь, я правильно отформатировал этот вопрос, поскольку знаю, что многие в stackoverflow относятся к этому очень серьезно. Это один из моих самых первых постов, поэтому я надеюсь, что я сделал это правильно и в соответствии со стандартами.
Подводя итог, есть ли способ индексировать массив символов с помощью массива или переменной? Спасибо за любую помощь! Кроме того, я студент, а MASM и Assembly — это то, чему я все еще очень много учусь и в чем пока не разбираюсь, поэтому, если я пропустил что-то очевидное, вот почему. Еще раз спасибо за вашу помощь!
РЕДАКТИРОВАТЬ: я предполагаю, что мне нужны как адрес буфера, так и parseNum для загрузки в регистры. Я попытался внести эти изменения, как показано здесь:
lea rbx, buffer
mov rax, parseNum
xor buffer[rax], 2
но я по-прежнему получаю те же ошибки, что и раньше.
РЕДАКТИРОВАТЬ: Благодаря некоторым очень полезным комментариям у меня получилось, вот код:
testJmp:
lea rdx, buffer
mov rbx, parseNum
mov al, [rdx rbx]
xor al, 2
mov [rdx rbx], al
add parseNum, 1
cmp parseNum, 4097
jne testJmp
по сути, буфер и parseNum должны быть загружены в регистры. Затем я получаю доступ к индексу, добавляя два регистра и перемещая их в al. Затем я могу применить xor и переместить его обратно в индекс.
Комментарии:
1. Сначала загрузите адрес
buffer
в регистр, используяlea
.2. @fuz Я только что попробовал это, добавив строку в верхней части цикла, которая гласит ` lea rbx, buffer`, а затем попытался загрузить в parseNum в качестве индекса, но все равно получил те же ошибки :/
3. Да, конечно, если вы тоже не загружаетесь
parseNum
в регистр, проблема не исчезнет. Оба должны быть в регистрах. Это связано с тем, что без/LARGEADDRESSAWARE:NO
переключателя нельзя предположить, что метки находятся в первых 2 ГБ памяти.4. @fuz: но код OP использует только
parseNum
один, а не с другим регистром, поэтому для этого следует использовать адресацию RIP-relative. Я думаю, что MASM всегда использует RIP-relative, когда это возможно, в отличие от GAS, где вам нужноmov rbx, parseNum[RIP]
. (Конечно, загрузка значения в регистр была бы более эффективной, чем сохранение его в памяти).5. Еще одна ошибка: если
parseNum
начинается с 0, и вы добавляете к нему 2 каждый раз, вы будете обрабатывать только каждый второй байт, и ваш цикл не завершится, потому что он никогда не будет равен нечетному числу 4097. Я предполагаю, что это не то, что вы хотите. Но трудно сказать вам, как исправить ваш код, потому что неясно, что он на самом деле должен делать.