I'm performing a program which seeks sum of square of floating point numbers provided in array
I've initialized ST1 and ST to +0.0 by using FLDZ twice and loaded the first Number Pointed by RSI to ST and multiplied by itself and added the result to ST1 and ran the above procedure through a loop
The array is array dd 15.0,7.0,9.0
The block which performs given operation is
mov rsi,array
fldz
fldz
xor rcx,rcx
mov cl,3
variance:
fld dword[rsi]
fmul dword[rsi]
fadd st1
add rsi,4
loop variance
fld st1
call display
mov rax,60
syscall
Consider display as a procedure which prints Floating Point Numbers stored in ST
Expected Output : 355.0000
Actual Output : 274.0000
Related
Code to convert from Fahrenheit to Celsius.
Input 100.0f Stored in the x8 integer register.
Output in the f0 register.
What is the error in the code?
Trying to implement the formula: Output = (100.0-32.0)*(5.0/9.0)
_start:
li x5,0x40a00000 # floating point representation of 5 in hex as per IEEE 754 notation. Storing in x5.
li x6, 0x41100000 # floating point representation of 9 in hex as per IEEE 754 notation. Storing in x6.
li x7, 0x42000000 # floating point representation of 32 in hex as per IEEE 754 notation. Storing in x7.
li x8, 0x42c80000 # floating point representation of 100 in hex as per IEEE 754 notation. Storing in x8. This is the input.
flw f0,0(x5) # Storing the value 5.0 in the floating point register f0
flw f1,0(x6) # Storing the value 9.0 in the floating point register f1
flw f2,0(x8) # Storing the value 100.0 in the floating point register f2
fdiv.s f0, f0, f1 # storing the value 5.0/9.0 in the register f0
flw f1, 0(x7) # storing the value 32.0 in the register f1.
fsub.s f2, f2, f1 # f2 = 100.0f – 32.0f = 68.0f
fmul.s f0, f0, f2 # f0 = 68.0f*(5.0f/9.0f) This is the output.
Compile Command:
~/spiking$ riscv64-unknown-elf-gcc -nostdlib -nostartfiles -T spike.lds faren.S -o faren.elf**
The flw instruction is used to load a floating-point value from memory. In your case, you use x5 as a pointer (which isn't what you intended).
To move the bits untouched from an X register to a floating-point register you can use fmv.w.x.
In the risc-v specification, it says that j is pseudocode for jal. I'm confused about how this works since the range of immediate values is different for j (25-bit immediate) and jal (20-bit immediate) - and also jalr with a 12-bit immediate.
Any clarification on how this translation is handled would be greatly appreciated!
No, immediate value size is not different for j and jal as official documentation say:
Plain unconditional jumps (assembler pseudoinstruction J) are encoded as a JAL with rd=x0.
Following instruction :
j offset
Will expand to
jal x0, offset
Maybe you thought that the 5bits that encode the rd register (x0) was included in offset, but not.
When objdump -S my_program, usually I can see the following indirect jmp instruction, which is typically used for switch/case jump table:
ffffffff802e04d3: ff 24 d5 38 2e 10 81 jmpq *-0x7eefd1c8(,%rdx,8)
How to understand the address -0x7eefd1c8? It means the table's base address is 0xffffffff802e04d3 - 0x7eefd1c8?
Also, how can I get -0x7eefd1c8 from ff 24 d5 38 2e 10 81?
decoding issue
Than you have to look at Intel Development Manuals
ff is JMP opcode (Jump near, absolute indirect) [1]
24 is a ModR/M byte [2] which means that SIB byte goes after it (JMP opcode has only one operand, so register field is ignored)
d5 is a SIB byte [2] which means that disp32 goes after that, Scale = 8 and Index = %rdx (in 32-bit mode, Index should be %edx) with no base.
38 2e 10 81 is a 4-byte disp32 operand. If you encode it as double word, you will get 0x81102e38 note that highest bit is set to 1. It is a sign bit meaning that value is encoded in Two’s Complement Encoding [3].
Converting from two's complement gives us expected number:
>>> print hex(0x81102e38 - (1 << 32))
-0x7eefd1c8
When processor executes that instruction in 64-bit mode, it reads 8 bytes from 0xffffffff81102e38 + (%rdx * 8) (original number is sign-extended) and puts that quad word into %rip [4].
References to manuals:
Vol.2A, section 3.2 INSTRUCTIONS (A-M), page 3-440
Vol 2, section 2.1.5 Addressing-Mode Encoding of ModR/M and SIB Bytes, pages 2-6..2-7
Vol 1, section 4.2.1.2 Signed Integers, page 4-4
Vol 2, section 2.2.1.3 Displacement, page 2-11
I'm doing an analysis of the shellcode found at http://www.shell-storm.org/shellcode/files/shellcode-211.php
I was wondering what this particular instruction does:
mov cx, 02001Q
I know it moves a value into cx, but I'm not sure what the Q stands for.
From the NASM docs;
NASM allows you to specify numbers in a variety of number bases, in a variety of ways: you can suffix H or X, D or T, Q or O, and B or Y for hexadecimal, decimal, octal and binary respectively
In other words, 02001Q means 2001 octal.
so this book "assembly language step by step" is really awesome, but it was sort of cryptic about how two's complement works when working on actual memory and register data. along with that, i'm not sure how signed values are represented in memory either, which i feel might be what's keeping me confused. anywho...
it says: "-1 = $FF, -2 = $FE and so on". now i understand that the two's complement of a number is itself multiplied by -1 and when added to the original will give you 0. so, FF is the hex equivalent of 11111111 in binary, and 255 in decimal. so my question is: what's the book saying when it says "-1 = $FF"? does it mean that -255 + -1 will give you 0 but also, which it didn't explicitly, set the OF flag?
so in practice... let's say we have 11h, which is 17 in decimal, and 00100001 in binary. and this value is in AL.
so then we NEG AL, and this will set the CF and SF, and change the value in AL to... 239 in decimal, 11101111 in binary, or EFh? i just don't see how that would be 17 * -1? or is that just a poorly worded explanation by the book, where it really means that it gives you the value you would need to cause an overflow?
thanks!
In two's complement, for bytes, (-x) == (256 - x) == (~x + 1). (~ is C'ish for the NOT operator, which flips all the bits in its operand.)
Let's say we have 11h.
100h - 11h == EFh
(256 - 17 == 239)
Note, the 256 works with bytes, cause they're 8 bits in size. For 16-bit words you'd use 2^16 (65536), for dwords 2^32. Also note that all math is mod 256 for bytes, 65536 for shorts, etc.
Or, using not/+1,
~11h = EEh
+1... EFh
This method works for words of all sizes.
what's the book saying when it says "-1 = $FF"?
If considering a byte only, the two's complement of 1 is 0xff (or $FF if using that format for hex numbers).
To break it down, the complement (or one's complement) of 1 is 0xfe, then you add 1 to get the two's complement: 0xff
Similarly for 2: the complement is 0xfd, add 1 to get the two's complement: 0xfe
Now let's look at 17 decimal. As you say, that's 0x11. The complement is 0xee, and the two's complement is 0xef - all that agrees with what you stated in your question.
Now, experiment with what happens when you add the numbers together. First in decimal:
17 + (-17) == 0
Now in hex:
0x11 + 0xef == 0x100
Since we're dealing with numeric objects that are only a byte in size, the 1 in 0x100 is discarded (some hand waving here...), and we result in:
0x11 + 0xef == 0x00
To deal with the 'hand waving' (I probably won't do this in an understandable manner, unfortunately): since the overflow flag (OF or sometimes called V for reasons that I don't know) is the same as the carry flag (C) the carry can be ignored (it's an indication that signed arithmetic occurred correctly). One way to think of it that's probably not very precise, but I find useful, is that leading ones in a negative two's complement number are 'the same as' leading zeros in a non-negative two's complement number.