-1

I was trying to do this arithmetic operation in assembly but i was getting the wrong answer every time, not sure how exactly I'm suppose to do it

These questions are from a textbook, and i do have the answers but trying to understand how to get that answer

The link contains the image which has question and my work as shown below

Address | value  ||   register value 
0x100      0xFF  ||    %rax     0x100
0x108      0xAB  ||    %rcx      0x1
0xll0      0x13  ||    %rdx      0x3
0x118      0xll  ||

|| lines are just to separate the two sides
Questions are 
Instruction                    Destination     Value
addq %rcx, (%rax)           :
subq %rdx,8(%rax)           :
imulq $16, (%ra,x,%rd.x,8)  :
incq 16 (%rax)              :
decq %rcx                   :
subq %rdx, %rax             :


Instruction                    Destination  Value
addq %rcx, (%rax)           :  0x100          ?
subq %rdx,8(%rax)           :  0x108          ?
imulq $16, (%ra,x,%rd.x,8)  :  0x118          ?
incq 16 (%rax)              :   ?             ?
decq %rcx                   :  %rcx          0x0
subq %rdx, %rax             :  %rax           ?
1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
  • 1
    Is this from CS:APP 3e global edition? Its practice problems often have invalid instructions, as in [CS:APP example uses idivq with two operands?](https://stackoverflow.com/q/57998998). **`imul` can't have a memory *destination*** (https://www.felixcloutier.com/x86/imul), so `imulq $16, (%ra,x,%rd.x,8)` is invalid. You also can't put commas and periods inside register names. `imulq $16, (%rax, %rdx, 8), %rsi` would be valid, multiply memory with immediate and put the result in a register (since unlike most instructions, imul-immediate takes 2 other operands.) – Peter Cordes Aug 22 '22 at 00:11
  • It is from CS:APP 3e - that's good to know. For example, I've also noticed they often make the scaling factor somethinf other than 1,2,4 or 8 – staplegun Aug 22 '22 at 00:29

2 Answers2

0

Do you have a basic knowledge of assembly language?

The first table appears to have the memory addresses / registers and their initial values.

If we take a look at the first instruction, it seems that it takes the value from the rcx register and write it in the memory address pointed by rax register.

so first you might ask yourself, what is the value of rax, now that value suppose to be a memory address where I suppose to write the value that's in rcx register.

whenever a register is being referenced with () i.e. (%rax), it means that the register's value should be taken as a memory address and the value that's in action is the value in that memory address (also called dereferencing).

stylo
  • 496
  • 4
  • 12
  • This is AT&T syntax, so the source operand is first. – 1201ProgramAlarm Sep 22 '19 at 17:01
  • Yes, i understand that but I'm sort of confused for the step after that. Do we add 0xFF with the rcx value, which is 0x1. If yes, then this is what I'm doing 1111 1111 -> 0xFF 0000 0001 -> %rcx 10000 0000 -> result? –  Sep 22 '19 at 17:02
  • @1201ProgramAlarm, Holy cow, you're right :O, editing – stylo Sep 22 '19 at 17:02
  • Taking rcx = 0x1 writing in the memory address pointed by reg rax that would be 0x100, so now the val of 0x100 is 0x1 So now when it's asking me for the value of that addq operation do I write 0x1 or a memory address? And what I did above, is that what you want me to do? –  Sep 22 '19 at 17:14
0

Here is an explanation for each:

addq %rcx, (%rax)

%rax points to the memory address 0x100. Therefore, our destination (which is our second operand) is 0x100. The value at %rcx is 0x1, which has a denary value of 1. Therefore, we want the value to be 1 + the value pointed to by 0x100. This value is 0xFF, which is 255, so our sum is 256. This is hex 0x100, which becomes our value.

subq %rdx, 8(%rax)

The format of sub S, D instructions is D <- D - S. In order to work out the destination, we see that this is base + displacement. So it is 0x100 + 0x8 to give us 0x108. At address 0x108 we have the value 0xAB, which is denary 171. 171 - the value at %rdx (which is 3) gives us 168 which is 0xA8.

imulq $16, (%rax, %rdx, 8)

Again, the destination is the second operand. We work this out by finding the value at %rax and adding 8 multiplied by the value at %rdx. So 0x100 (which is 256) + 8 * 0x3 (which is 3). This gives us 280, which is 0x118 in hex. Hence, 0x118 is our destination.

To work out the value, we take the value held at 0x118, which is 0x11 and multiply its denary value, which is 17, by the immediate value 16. This gives us 272. Converting this back to hex, we get 0x110.

incq 16(%rax)

First, we work out the address of the value we want increment. 16 + the value at %rax, is 16 + the value at 0x100, so 16 + 256 = 272. This is 0x110 - our hex address. The value at 0x100 is 0x13 + 1 is 0x14. So our value os 0x14.

decq %rcx

The destination is %rcx which holds the value 0x1. Subtracting 1 we get 0x0, our value.

subq %rdx, %rax

The destination is the second operand, so it is the address %rax holds - 0x100. The value is calculated by taking the value of 0x100 (256) and subtracting the value of %rdx (3) to get 253. This is 0xFD.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
staplegun
  • 79
  • 10
  • `imulq $16, (%rax, %rdx, 8)` isn't a valid instruction; it can only have a register destination. https://www.felixcloutier.com/x86/imul. I added a [comment about this](https://stackoverflow.com/questions/58051366/im-confused-about-this-arithmetic-operators#comment129690854_58051366) in more detail under the question. If it was encodeable, though, yes, it would be equivalent to `shlq $4, (%rax, %rdx, 8)` which is a valid instruction. Left-shifting by 4 the qword at address `[rax + rdx*8]` – Peter Cordes Aug 22 '22 at 00:14
  • 1
    Also, multiplying by 16 is easier in hex than decimal! `x * 0x10` just left shifts by 4, or one hex digit, appending a 0 to the hex representation. Exactly like multiplying by 10 in base 10. Converting to decimal and back seems like unnecessary mental effort in most of your steps. Especially when adding multiples of 8, just remember that 8+8 = 0x10 and the address math is easy to do in your head. – Peter Cordes Aug 22 '22 at 00:19