1

I have read similar posts regarding this question, but just can't find anything that's helping me fix my problem. Essentially, I want to change an entry in a character array at a specific point, so simply indexing it. I know how to do that with a magic number (ie just putting in buffer[2] or something like that) but I am getting errors when I try to index the character array with a number value stored in a register or a QWORD.

So I have a char array called buffer

buffer BYTE 4097 DUP (0)

and I also have QWORD named parseNum

parseNum QWORD 0

Here is the section of code giving me problems:

testJmp:
mov rbx, parseNum
xor buffer[rbx], 2
add parseNum, 2
cmp parseNum, 4097
jne testJmp

This code is supposed to loop through the char array and apply a XOR operand to each entry. However I can only do that if I can index at a value that changes with each loop. When I try to just use xor buffer[parseNum], 2 I get an error that reads error A2101: cannot add two relocatable labels at that line of code. When I try moving parseNum into rbx and then putting in rbx as the index, I also get an error that reads, error LNK2017: 'ADDR32' relocation to 'buffer' invalid without /LARGEADDRESSAWARE:NO. I'm at a total lose and am completely stuck. Hopefully I formatted this question properly as I know many on stackoverflow take that very seriously. This is one of my very first posts so I hope I did that properly and up to standards.

To summarize, is there a way to index a char array with an array or variable? Thank you for any help! Also, I am a student, and MASM and Assembly is something I am still very much learning and not skilled at yet, so if there's something obvious I missed, that's why. Again, thank you for your help!

EDIT: I guess I need both buffer's address and parseNum to loaded into registers. I tried making these changes, as seen here:

lea rbx, buffer
mov rax, parseNum
xor buffer[rax], 2

but I still get the exact same errors as before.

EDIT: Thanks to some very helpful comments, I got it working, here is the code:

    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

essentially, the buffer and parseNum must be loaded into registers. Then I access the index by added the two registers and moving that to al. Then I can apply xor and mov it back into the index.

Colt Magri
  • 19
  • 3
  • Load the address of `buffer` into a register using `lea` first. – fuz Jan 15 '21 at 20:30
  • @fuz I just tried that, adding a line at the top of the loop that reads ` lea rbx, buffer ` and then tried loading in parseNum as the index, but still got the same errors :/ – Colt Magri Jan 15 '21 at 20:34
  • 1
    Yeah of course if you don't load `parseNum` into a register, too, the problem won't go away. Both need to be in registers. This is because without the `/LARGEADDRESSAWARE:NO` switch, labels cannot be assumed to reside in the first 2 GB of memory. – fuz Jan 15 '21 at 20:38
  • @fuz: but the OP's code only ever uses `parseNum` alone, not with another register, so RIP-relative addressing should be used for that. I think MASM always uses RIP-relative when possible, unlike GAS where you'd need `mov rbx, parseNum[RIP]`. (Of course, loading the value into a register would be more efficient than keeping it in memory). – Peter Cordes Jan 15 '21 at 20:41
  • @fuz yeah, I just updated my post to say that I tried loading both into registers, and I'm seeing no change, same exact errors at same exact line of code. I've been stumped on this for so long ha – Colt Magri Jan 15 '21 at 20:42
  • Your updated code still uses `buffer` and a register in the same instruction, preventing RIP-relative addressing!!! You have to write instructions that reference that register, some previous instruction isn't going to magically change how an instruction assembles. Basically the same problem as [Mach-O 64-bit format does not support 32-bit absolute addresses. NASM Accessing Array](https://stackoverflow.com/q/47300844), but that shows syntax for NASM, not for MASM. – Peter Cordes Jan 15 '21 at 20:43
  • @PeterCordes sorry, masm is a new language for me and as you can guess, I struggle with it. I had a feeling that yeah, loading it into a register and just that wouldn't result in a change, but I thought I'd give it a try. Once I load buffers address into the register, where do I got from there? Any suggestions would be much appreciated – Colt Magri Jan 15 '21 at 20:47
  • `[reg+reg]` obviously. [Referencing the contents of a memory location. (x86 addressing modes)](https://stackoverflow.com/q/34058101) – Peter Cordes Jan 15 '21 at 20:47
  • 2
    Another bug: if `parseNum` starts at 0 and you add 2 to it every time, you will only process every other byte, and your loop will not terminate because it will never equal the odd number 4097. I assume that is not what you want. But it's hard to tell you how to fix your code because it's unclear what it is actually supposed to do. – Nate Eldredge Jan 15 '21 at 20:48
  • Thanks everyone! Especially @PeterCordes for the [reg+reg], that got it working. And yes NateEldredge thanks for pointing that out, it should be 1 not 2 for the loop. This is solved, anyone know how I can label it as such? – Colt Magri Jan 15 '21 at 21:02

0 Answers0