### Author Topic: Using idiv  (Read 1323 times)

#### JohnG

• Jr. Member
• Posts: 33
##### Using idiv
« on: January 13, 2022, 11:26:27 PM »
Hi all,

It seems simple enough, but what am I doing wrong, just trying things at the moment with no luck.

I did read somewhere that the divisor had to be a smaller data size than the dividend ?

start:
and     rsp,    -16  ;stack align

mov     rax,    [a]    ; a = 100  dividend
xor     rdx,    rdx
mov     r8,    [sum]  ; sum = 4
idiv    dword[r8]
mov     rcx,    fmt
mov     rdx,    [r8]   ; value to print
sub     rsp,    32      ; shadow space
call    printf

I may be stomping on registers ?

John

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2639
• Country:
##### Re: Using idiv
« Reply #1 on: January 13, 2022, 11:53:42 PM »
Here you are moving the number 4 into r8
Code: [Select]
`mov     r8,    [sum]  ; sum = 4`
Here you are dividing by the number at address 4!
Code: [Select]
`        idiv    dword[r8]        `
Try:
Code: [Select]
`idiv r8`
Warning: untested!

Best,
Frank

#### debs3759

• Global Moderator
• Full Member
• Posts: 208
• Country:
##### Re: Using idiv
« Reply #2 on: January 13, 2022, 11:57:41 PM »
idiv dword[r8] divides rax by the value stored at the memory address pointed to by r8. You want

Code: [Select]
`idiv    r8`
I also don't think using dword (32-bits) with a 64-bit register would be right, and am sure you don't need it anyway.
My graphics card database: www.gpuzoo.com

#### JohnG

• Jr. Member
• Posts: 33
##### Re: Using idiv
« Reply #3 on: January 14, 2022, 12:01:52 AM »
Hi Frank,

I tried that, and I get a message   "operation size not specified"

Anyway to avoid that damn Anti-spam task ?

#### JohnG

• Jr. Member
• Posts: 33
##### Re: Using idiv
« Reply #4 on: January 14, 2022, 12:10:08 AM »
hi,

Made the other changes and program just crashes, no errors showing when compiling.

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2639
• Country:
##### Re: Using idiv
« Reply #5 on: January 14, 2022, 01:10:18 AM »
Hi JohnG,
"other changes"? Just remove the square brackets from r8.

I do not get that error.

I think if you post a few more times, the  Forum will believe you are human.. Sorry 'bout that.

Best.
Frank

#### JohnG

• Jr. Member
• Posts: 33
##### Re: Using idiv
« Reply #6 on: January 14, 2022, 02:26:51 AM »
Hi all,

Yes Frank the Forum says I am human now, that could be argued by many though.

I put the x64dbg on it and it does seem to be dividing ok, some issue with the printf, which was working but not now, go figure.

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2639
• Country:
##### Re: Using idiv
« Reply #7 on: January 14, 2022, 03:32:16 AM »
Good there is some progress with the forum, anyway.

I haven't run Windows since win98 was current. 32 bit code was similar Linux and Windows. 64 bit code not so! I can't help you much.

Code examples are always welcome!

Best,
Frank

#### JohnG

• Jr. Member
• Posts: 33
##### Re: Using idiv
« Reply #8 on: January 14, 2022, 10:06:45 PM »
Hi all,

ok, got the little test program running again.

Back to the idiv.   I see you get a quotient and a remainder  but what if you want to know the decimal part.

as in   155/4 = 38.75    what I get is  38 in rax,  3 in rdx   which is  0.75 ie 3/4

John

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2639
• Country:
##### Re: Using idiv
« Reply #9 on: January 15, 2022, 12:33:07 AM »
Oh my!

As the name suggests, idiv is integer division. You want floating point.

In the good old days, the floating point unit, if you had one, would do this with "fdiv", Gettin the number tp/from float to ascii was the tricky part.

Nowadays, it's done with xmm or mmx - I'm not even sure which. Way above my pay grade.

Good luck!

Best,
Frank

?
Section A.4.60: DIVPD: Packed Double-Precision FP Divide
?

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2639
• Country:
##### Re: Using idiv
« Reply #10 on: January 15, 2022, 01:37:47 AM »
This is not even close to what you want. An old DOS com file. Won't even run on modern hardware. It does show a decimal point.

Best,
Frank

Code: [Select]
`;-----------------------------------------------; converts centigrade to fahrenheit, & visa versa;; nasm -f bin -o myfile.com myfile.asm;--------------------------------------org 100hBUFSIZ equ 8section .data    prompt0 db 13, 10, 7, 'Pay Attention!!!', 13, 10, '\$'    prompt1 db 13, 10, 'This humble program will convert', 13, 10            db 'degrees centigrade to degrees Fahrenheit,', 13, 10            db 'or Fahrenheit to centigrade (Celsius).', 13, 10            db 'Please enter "C" or "F" to indicate the', 13, 10            db 'temperature units in which you will INPUT', 13, 10            db 'the value to be converted.', 13, 10, 10  , '\$'    promptc db 'Please enter degrees C to convert to F:', 13, 10, '\$'    promptf db 'Please enter degrees F to convert to C:', 13, 10, '\$'    that    db 13, 10, "That's \$"    degrees db ' degrees \$'    bye     db 13, 10, 10, "Thanks for playing!", 13, 10, '\$'    word_10 dw 10   ; multiplier for the float-to-ascii routine                    ; for C->F, F->C routines    float_32 dq 32.0    float_5  dq 5.0    float_9  dq 9.0section .bss    buffer resb BUFSIZ + 2     ; buffer for our input string    result_units resb 1        ; holds 'C' or 'F'    numbuf resb 20h            ; buffer for ftoa    bcdbuf rest 1              ; 10 byte scratch area for ftoa;--------------------section .text; cheap-a** cls - reset text mode    mov ax, 3    int 10hinstruct:; tell 'em what we're gonna do, and ask for input    mov dx, prompt1    mov ah, 9    int 21h; get input - one key, no echo    mov ah, 8    int 21h; force uppercase    and al, 0DFh; did they get it right?    cmp al, 'C'    je do_c2f    cmp al, 'F'    je do_f2c; smack their a**, and make 'em do it over    mov dx, prompt0    mov ah, 9    int 21h    jmp short instruct; store the letter we'll display at the end; we also use it as a "flag" to decide f->c or c->f; and set up appropriate promptdo_c2f:    mov byte [result_units], 'F'    mov dx, promptc    jmp short bothdo_f2c:    mov byte [result_units], 'C'    mov dx, promptfboth:; display the prompt, "C" or "F", asking for input    mov ah, 9    int 21h; get string input, set "max size" first    mov byte [buffer], BUFSIZ    mov ax, 0C0Ah    mov dx, buffer    int 21h; since atof expects a zero-terminated string, do so.    mov bl, [buffer + 1]    xor bh, bh    mov byte [buffer + 2 + bx], 0; convert the string to a float in st(0); remember that input text starts at 2 bytes into the buffer    mov si, buffer + 2    call atof    jnc good_num; if they gave us trash, give 'em trash back; and make 'em do it over    mov dx, prompt0    int 21h    mov dx, promptc    cmp byte [result_units], 'F'    je both    mov dx, promptf    jmp short bothgood_num:; okay, they did right, do the calculation they want    cmp byte [result_units], 'C'    jne calc_c2f    fsub qword [float_32]    fmul qword [float_5]    fdiv qword [float_9]    jmp short displaycalc_c2f:    fmul qword [float_9]    fdiv qword [float_5]    fadd qword [float_32]; Whew! That was tough!display:; convert st(0) to ascii string at di - cx decimal places    mov cx, 2    mov di, numbuf    call ftoa; ftoa returns a zero-terminated string,; fix it for int 21h/9 - '\$'-terminate    dec direterminate:    cmp byte [di + 1], 1    inc di    jnc reterminate    mov byte [di], '\$'; tell 'em what we're going to do    mov ah, 9    mov dx, that    int 21h ; tell 'em the number    mov dx, numbuf    int 21h; and the units    mov dx, degrees    int 21h    mov ah, 2    mov dl, [result_units]    int 21h; say Buhbye - enhancement - go again?    mov ah, 9    mov dx, bye    int 21hexit:    mov ah,4Ch    int 21h;------------------------------------------------; atof - converts ascii string to float; expects: si pointed to zero-terminated string; returns: float in st(0);          carry set if invalid digit encountered;-------------------------------------------------atof:    push ax    push bx    push cx    push dx    push di    push si    xor bx, bx    xor cx, cx    dec cx                    ; set cx FFFF - no point found    xor dx, dx    mov byte [bcdbuf + 9], 0  ; assume positive    mov di, si                ; save our "beginning of buffer".af0:    mov al, [si]    inc si    cmp al, '-'    jnz .notneg    mov byte [bcdbuf + 9], 80h    jmp short .af0.notneg:    cmp al, '.'    jnz .notpt    inc cx    jmp short .af0.notpt:    cmp al, ' '    jz .af0    cmp cx, 0FFFFh    jz .af05    inc cx.af05    or al, al        ; end of string?    jnz .af0    dec si    dec si    cmp cx, 0FFFFh    jnz .af07    xor cx, cx    jmp short .af1.af07    dec cx.af1:    cmp si, di    jc .done    mov al, [si]    dec si    cmp al, ' '    jz .af1    cmp al, '-'    jz .af1    cmp al, '.'    jz .af1    cmp al, 3Ah    jnc .invalid    cmp al, 30h    jc .invalid    and al, 0Fh    or dh, dh    jnz .notfirst    or dl, al    inc dh    jmp short .af1.notfirst:    shl al, 4    or dl, al    mov [bcdbuf + bx], dl    xor dx, dx    inc bx    jmp .af1.invalid    stc    jmp short .done3.done    or dh, dh    jz .padbcd    and dl, 0Fh    mov [bcdbuf + bx], dl    inc bx.padbcd    cmp bx, byte 9    jz .done2    mov byte [bcdbuf + bx], 0    inc bx    jmp short .padbcd.done2    fbld [bcdbuf]    or cx, cx    jz .done25.tendiv:    fidiv word [word_10]    loop .tendiv.done25    clc.done3:    pop si    pop di    pop dx    pop cx    pop bx    pop ax    ret;--------------------------------------------;-----------------------------------------------------; ftoa - converts floating point to string;; Based on some code "sponged" from a post to clax; From: "Jim Morrison" <astrolabe at ntplx dot net>;; Expects: Number to convert is on stack top - st(0);          di points to buffer to store string;          cx = Decimal Places.;-------------------------------------------------------------ftoa:    push ax    push cx    push dx    push di    push si    mov dx, cx           ; save a copy of dec places                         ; if no decimal (integer)    jcxz .f2a2           ; skip multiply by ten loop.f2a1:                   ; else loop to "scale" number    fimul word [word_10]    loop .f2a1.f2a2:    fbstp [bcdbuf]       ; convert to bcd and store    mov si, bcdbuf       ; we'll pull digits from there    mov cx, 9.f2a3:    lodsb                ; get a pair of digits    mov ah, al           ; move a copy to ah    shr ah, 4            ; shift out low nibble, keeping high    and ax, 0F0Fh        ; mask out the digits we want    add ax, 3030h        ; convert 'em both to ascii    push ax    mov al, ah           ; swap and store the other digit    push ax    loop .f2a3           ; until done    cmp byte [bcdbuf+9], 0 ; sign flag at bcdbuf + 9 ?    je .f2a6    mov al, '-'           ; minus sign if we need it    stosb                 ; store it at front of our string.f2a6:    mov cx, 18    xor dh, dh    inc dl.poploop    pop ax    cmp al, '0'    jnz .store    or dh, dh    jnz .store    jmp short .nostore.store    stosb    inc dh.nostore    cmp cl, dl    jne .nopoint    or dh, dh       ; if we haven't encountered a non-zero    jnz .nolz    mov al, '0'     ; put a zero before the decimal point    stosb.nolz    mov al, '.'           ; decimal point    stosb                 ; and store it    inc dh.nopoint    loop .poploop    mov al, 0    stosb    pop si    pop di    pop dx    pop cx    pop ax    ret;--------------------------------------------------`

#### JohnG

• Jr. Member
• Posts: 33
##### Re: Using idiv
« Reply #11 on: January 15, 2022, 01:52:56 AM »
Hi,

yeah, I read about the xmm0/1/2 etc  registers but not sure how it all goes together. Every example I have read only do the easy divide like   90/9  so there is no remainder.

I will have a read of the example you posted here, any hints are good.

#### JohnG

• Jr. Member
• Posts: 33
##### Re: Using idiv
« Reply #12 on: January 16, 2022, 10:49:14 PM »
Hi All,

Finally got my little testing program to work with divide (floating point)

A page I found this morning may be of use to other also.

https://github.com/PoCc001/ASM-Math/blob/main/SSE/math64.asm

« Last Edit: January 16, 2022, 10:51:44 PM by JohnG »