flat assembler
Message board for the users of flat assembler.
Index
> Linux > Reading int or float from the command line Goto page 1, 2 Next |
Author |
|
revolution 19 Apr 2017, 17:36
You are using an integer instruction (add) on floating point values. Instead you will need to use a floating point instruction (addsd or equivalent) to do the addition.
|
|||
19 Apr 2017, 17:36 |
|
dstyl 19 Apr 2017, 17:42
thanks a lot i tried it out and replaced add with addsd [sum],rax but im getting an opcode error now.
|
|||
19 Apr 2017, 17:42 |
|
revolution 19 Apr 2017, 17:53
Using XMM is not quite the same as the integer instructions. You'll need to load the value from RAX into one of the XMM registers first, and then do the addsd. But AFICT there is no direct instruction to transfer RAX into XMM, so you'll need to place RAX in memory first, and then load into XMM from memory.
|
|||
19 Apr 2017, 17:53 |
|
dstyl 19 Apr 2017, 18:02
I ve commented out some lines just to check if the movsd works and there is the error. is there
another opcode to move a float from mem to reg? Code: ; ----------------------------------------------------------------------------- ; 64-bit program that treats all its command line arguments as floating point ; number and displays their average as a floating point number. This program ; uses a data section to store intermediate results, not that it has to, but ; only to illustrate how data sections are used. ; ----------------------------------------------------------------------------- global main extern atof extern printf default rel section .text main: dec rdi ;argc-1, da wir den programm namen ignorieren jz nothingToAverage ;wenn rdi == 0 mov [count], rdi ;speichere args in [count] accumulate: push rdi ;sichere reg vor atof aufruf push rsi mov rdi, [rsi+rdi*8] ;argv[rdi] c alignment beachten! call atof ;rax enthält den wert von arg pop rsi ;wiederherstellen der reg nach pop rdi ;aufruf von atof add [sum], rax ;summieren der werte dec rdi ;argc runterzählen jnz accumulate ;wiederhole wen argc != 0 average: movsd xmm0, [sum] ;verschiebe signed double ; movsd xmm1, [count] ;in xmm register ; divsd xmm0, xmm1 ;xmm0 ist sum/count mov rdi, format ;erste arg für printf mov rax, 1 ;printf hat var args es gibt 1 nicht sub rsp, 8 ;align des stackpointers call printf ;printf(format, sum/count) add rsp, 8 ;wiederherstellen des stackpointers ret nothingToAverage: mov rdi, error xor rax, rax call printf ret section .data count: dq 0 sum: dq 0 format: db "%g", 10, 0 error: db "There are no cmdcmnds to average", 10, 0 |
|||
19 Apr 2017, 18:02 |
|
cod3b453 19 Apr 2017, 18:06
There is a movd xmm,reg64 (66 0F 6E /r) but seems FASM doesn't support it syntactically and instead (re)uses movq xmm,reg64 which seems to assemble to the expected opcode [and kinda makes more sense really].
|
|||
19 Apr 2017, 18:06 |
|
revolution 19 Apr 2017, 18:15
Okay, movq is the one.
Code: movq xmm0,rax addsd [sum],xmm0 |
|||
19 Apr 2017, 18:15 |
|
dstyl 19 Apr 2017, 18:39
Thanks for your time but it still doesnt work now i replaced addsd because it says invalid opcode so now i have
Code: ; ----------------------------------------------------------------------------- ; 64-bit program that treats all its command line arguments as floating point ; number and displays their average as a floating point number. This program ; uses a data section to store intermediate results, not that it has to, but ; only to illustrate how data sections are used. ; ----------------------------------------------------------------------------- global main extern atof extern printf default rel section .text main: dec rdi ;argc-1, da wir den programm namen ignorieren jz nothingToAverage ;wenn rdi == 0 mov [count], rdi ;speichere args in [count] accumulate: push rdi ;sichere reg vor atof aufruf push rsi mov rdi, [rsi+rdi*8] ;argv[rdi] c alignment beachten! call atof ;rax enthält den wert von arg pop rsi ;wiederherstellen der reg nach pop rdi ;aufruf von atof ; movq xmm0,rax movq [sum],xmm0 ; ; add [sum], rax ;summieren der werte dec rdi ;argc runterzählen jnz accumulate ;wiederhole wen argc != 0 average: ; movsd xmm0, [sum] ;verschiebe signed double ; movsd xmm1, [count] ;in xmm register ; divsd xmm0, xmm1 ;xmm0 ist sum/count mov rdi, format ;erste arg für printf mov rax, 1 ;printf hat var args es gibt 1 nicht sub rsp, 8 ;align des stackpointers call printf ;printf(format, sum/count) add rsp, 8 ;wiederherstellen des stackpointers ret nothingToAverage: mov rdi, error xor rax, rax call printf ret section .data count: dq 0 sum: dq 0 format: db "%g", 10, 0 error: db "There are no cmdcmnds to average", 10, 0 |
|||
19 Apr 2017, 18:39 |
|
redsock 19 Apr 2017, 22:00
Rather than fixup your code, I wrote an equivalent with my own x86_64 linux library.
Of note in yours however, atof returns its result in xmm0, not rax. Anyway, my morning coffee writeup works and should help cheers. Code: include 'HeavyThing-1.19/ht_defaults.inc' include 'HeavyThing-1.19/ht.inc' public _start falign _start: call ht$init sub dword [argc], 1 jz .nothingtodo ; store our double accumulator and counter in callee-saves ; (xmm regs are not callee-save) xor r15d, r15d xor ebx, ebx .accumulate: ; accumulate arguments in reverse order mov rdi, [argv] call list$pop_back ; HeavyThing turns argv into strings, save it mov r12, rax ; convert it to double mov rdi, rax call string$to_double ; accumulate and increase counter movq xmm1, r15 addsd xmm1, xmm0 movq r15, xmm1 add ebx, 1 ; free the string mov rdi, r12 call heap$free ; keep going sub dword [argc], 1 jnz .accumulate ; prepare our argument for double to string movq xmm0, r15 ; convert our counter to a double cvtsi2sd xmm1, ebx ; divide them divsd xmm0, xmm1 ; display the result ; string$from_double needs mode and precision mov edi, double_string_normal mov esi, 15 call string$from_double mov r12, rax mov rdi, rax call string$to_stdoutln mov rdi, r12 call heap$free ; exit cleanly mov eax, syscall_exit xor edi, edi syscall .nothingtodo: mov rdi, .nothingmsg call string$to_stderrln mov eax, syscall_exit mov edi, 1 syscall cleartext .nothingmsg, 'Nothing to average.' include 'HeavyThing-1.19/ht_data.inc' Code: # ./average 3 3 3 3 3 # ./average 3 3 3 3 5 3.4 # ./average 3 3 3 3 9 11 5.333333333333333 |
|||
19 Apr 2017, 22:00 |
|
fasmnewbie 20 Apr 2017, 04:38
You don't need atof in there. Just use atoi then convert it to double using CVTxxx
sub rsp,8 sub rdi mov [count],rdi ... loop call atoi cvtsi2sd... convert integer in rax to float (double) addsd some_accumulator after the loop cvtsi2sd [count] divsd some_accumulator, [count] printf add rsp,8 ret |
|||
20 Apr 2017, 04:38 |
|
revolution 20 Apr 2017, 04:45
fasmnewbie wrote: You don't need atof in there. |
|||
20 Apr 2017, 04:45 |
|
fasmnewbie 20 Apr 2017, 05:30
@revolution.
Look at his comment lines. It is clear he's trying to solve an ATOI problem but thought he could use ATOF as the solution. Also look at his input attempt. This type of question is a familiar question among beginners so we should be able to anticipate beginner's confusions and intentions. Which is something like so; Code: global main extern atoi extern printf section .data formt db 'Average = %f',0ah,0 section .code main: sub rsp,8 mov r14,rdi sub r14,1 mov r13,r14 ;count mov r15,rsi pxor xmm8,xmm8 ;accumulator .next: mov rdi,[r15+r14*8] call atoi cvtsi2sd xmm0,rax ;convert int to double addsd xmm8,xmm0 ;add to accumulator sub r14,1 jnz .next cvtsi2sd xmm0,r13 ;convert count to double divsd xmm8,xmm0 ;average is here movq xmm0,xmm8 ;prepare for printf mov rdi,formt mov rax,1 call printf add rsp,8 ret |
|||
20 Apr 2017, 05:30 |
|
redsock 20 Apr 2017, 05:53
While I appreciate what you're saying @fasmnewbie, the OP actually used xmm regs AND atof, which together suggest the need for floating point math. My example (though I didn't bother to include example output) does exactly that with arbitrary floating point input. Your example is much cleaner though for whole integers. Maybe there is some middle ground for people who struggle with things.
Code: # ./average 3.1415 1.0003e-1 6.283 3.1748433333333335 |
|||
20 Apr 2017, 05:53 |
|
fasmnewbie 20 Apr 2017, 06:24
@redsock
My suspicion is not baseless though. I see traces of previous ATOI attempts in both his side comments and his implied input (3 3 3 3...). But when the result was not that satisfying, he resorted to ATOF. Mixing both FP and integer is not a beginner's material IMO. He probably needs more than one externs from the C library if such was the case. |
|||
20 Apr 2017, 06:24 |
|
fasmnewbie 20 Apr 2017, 06:59
This is a quick fix to my original progam above, just in case the user can key in both FP and integer values at the command-line;
Code: global main extern atoi extern atof extern strchr extern printf section .data formt db 'Average = %f',0ah,0 section .code main: sub rsp,8 ;align the stack mov r14,rdi sub r14,1 mov r13,r14 ;count mov r15,rsi ;command string pointer pxor xmm8,xmm8 ;accumulator .next: mov rdi,[r15+r14*8] mov rsi,'.' call strchr test rax,rax jnz .float mov rdi,[r15+r14*8] call atoi cvtsi2sd xmm0,rax ;convert int to double jmp .ints .float: mov rdi,[r15+r14*8] call atof .ints: addsd xmm8,xmm0 ;add to accumulator sub r14,1 jnz .next cvtsi2sd xmm0,r13 ;convert count to double divsd xmm8,xmm0 ;average is here movq xmm0,xmm8 ;prepare for printf mov rdi,formt mov rax,1 call printf add rsp,8 ret Haven't given it a thorough test. The output: Code: ~/fasm $ ./prog 3 .5 1.6 7 9 10.12 11.654 0.1 -.7 Average = 4.697111 |
|||
20 Apr 2017, 06:59 |
|
fasmnewbie 20 Apr 2017, 07:04
What am I doing. This is a FASM forum ;D
Code: format ELF64 public main extrn atoi extrn atof extrn strchr extrn printf section '.data' writeable formt db 'Average = %f',0ah,0 section '.code' executable main: sub rsp,8 ;align the stack mov r14,rdi sub r14,1 mov r13,r14 ;count mov r15,rsi ;command string pointer pxor xmm8,xmm8 ;accumulator .next: mov rdi,[r15+r14*8] mov rsi,'.' call strchr test rax,rax jnz .float mov rdi,[r15+r14*8] call atoi cvtsi2sd xmm0,rax ;convert int to double jmp .ints .float: mov rdi,[r15+r14*8] call atof .ints: addsd xmm8,xmm0 ;add to accumulator sub r14,1 jnz .next cvtsi2sd xmm0,r13 ;convert count to double divsd xmm8,xmm0 ;average is here movq xmm0,xmm8 ;prepare for printf mov rdi,formt mov rax,1 call printf add rsp,8 ret ;gcc -m64 prog.o -o prog |
|||
20 Apr 2017, 07:04 |
|
dstyl 20 Apr 2017, 07:51
Thanks for your help to all i learned alot , but i have already an atoi solution i would like redsock said to use atof so the user could enter doubles. You all have way better solutions than mine. Sorry for the misleading comments.
|
|||
20 Apr 2017, 07:51 |
|
fasmnewbie 20 Apr 2017, 09:56
@dstyl
good to know you managed to find the solution. Don't forget to share it with us here so future visitors of this thread can learn many things from the discussions here. Help this board grows. Don't be shy to share your solution. We can give you small fixes if there's a problem. If it's not a problem, you can change the thread's title to something more accurate to the problems discussed here to make it more search-friendly. Like "Reading int or float from the command line" or similar. Regards. |
|||
20 Apr 2017, 09:56 |
|
dstyl 20 Apr 2017, 10:12
Thanks for the advice ive changed the thread title, i only have the error when i try to place a float value from mem into the xmm registers, here is my atoi solution but i checked and atof also works just using xmm regs doesnt work. My solution is not as short as yours
Code: ; ----------------------------------------------------------------------------- ; 64-bit program that treats all its command line arguments as integers and ; displays their average as a floating point number. This program uses a data ; section to store intermediate results, not that it has to, but only to ; illustrate how data sections are used. ; ----------------------------------------------------------------------------- global main extern atoi extern printf default rel section .text main: dec rdi ;argc-1, da wir den programm namen ignorieren jz nothingToAverage ;wenn rdi == 0 mov [count], rdi ;speichere args in [count] accumulate: push rdi ;sichere reg vor atoi aufruf push rsi mov rdi, [rsi+rdi*8] ;argv[rdi] c alignment beachten! call atoi ;rax enthält den wert von arg pop rsi ;wiederherstellen der reg nach pop rdi ;aufruf von atoi add [sum], rax ;summieren der werte dec rdi ;argc runterzählen jnz accumulate ;wiederhole wen argc != 0 average: cvtsi2sd xmm0, [sum] ;konvertiere signed dw int zu signed cvtsi2sd xmm1, [count] ;double precision float divsd xmm0, xmm1 ;xmm0 ist sum/count mov rdi, format ;erste arg für printf mov rax, 1 ;printf hat var args es gibt 1 nicht sub rsp, 8 ;align des stackpointers call printf ;printf(format, sum/count) add rsp, 8 ;wiederherstellen des stackpointers ret nothingToAverage: mov rdi, error xor rax, rax call printf ret section .data count: dq 0 sum: dq 0 format: db "%g", 10, 0 error: db "There are no cmdcmnds to average", 10, 0 but it works ^^ do you know a solution to the xmm reg problem? |
|||
20 Apr 2017, 10:12 |
|
fasmnewbie 20 Apr 2017, 12:28
@dystl
It doesn't work that way with ATOI. ATOI takes only the integer part of the string input and ignores the fraction ./average 3.4 3 3 5.6 Is actually interpreted by ATOI as ./average 3 3 3 5 And not even rounding it. In this case, you have to set your own input control / policy for the input values. It's either integer only or floating point only (using ATOF). You're confusing the input values with the output values (which are floats in both cases anyway). My last example however takes both types of input. I hope I understood what your real questions are because you're sending mixed messages. |
|||
20 Apr 2017, 12:28 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.