the question is to solve the following using only ax,bp,sp
b*c/d+(e-f)*g wh,b=10,c=4,d=5,e=8,f=3,g=2
the answer is suppose to be 18 but i obtain 14
here is my code
org 100
section .data
section .text
start:
mov ax,3
push ax
mov bp,sp
mov ax,8
sub ax,
push ax
mov ax,2
mov bp,sp
imul ax,
push ax
mov ax,10
imul ax,4
mov bp,sp
mov bp,
div bp
mov bp,
mov ax,bp
mov bp,




add ax,bp









int 20h
Posted on 2010-04-24 06:25:44 by foxynash
foxynash,

mov ax, bp trashes the result of your previous calculations.

mov bp, uses value that you didn't pushed on stack (actually it's trails of debug interrupt handler's "save/restore registers" code if you use t or g command before that mov, or any trash).

div r16 uses dx too (ax = dx:ax/r16; luckily dx==0 in most cases).

Mixed signed/unsigned arithmetics? This can lead to a problem (not in this simple case).

You need only one word of stack to do this (because * has more priority than +).
Posted on 2010-04-24 10:51:58 by baldr

foxynash,

mov ax, bp trashes the result of your previous calculations.

mov bp, uses value that you didn't pushed on stack (actually it's trails of debug interrupt handler's "save/restore registers" code if you use t or g command before that mov, or any trash).

div r16 uses dx too (ax = dx:ax/r16; luckily dx==0 in most cases).

Mixed signed/unsigned arithmetics? This can lead to a problem (not in this simple case).

You need only one word of stack to do this (because * has more priority than +).



thanks bald... please tell me what is the right operation to use??? I just want to copy the first result obtained into  bp so that i can later add it with the one in ax
Posted on 2010-04-25 10:40:25 by foxynash
This is quite a tricky question, Foxynash! Not that hard to do - quite easy, "if you want to do it *that* way"... But hard to know how you're "supposed" to do it.

One way to figure out how to do stuff is to write it up in C, and observe what the compiler does with it. If you turn up optimization, the compiler is going to optimize everything down to "mov ax, 18"! We can do the same with Nasm...


mov ax, 10 * 4 / 5 + (8 - 3) * 2


There ya go! Somehow, I don't think that's going to get you a good grade, however. I suppose you're supposed to give the CPU some exercise. Well, I can see that I probably want to do the stuff in the parentheses first...


mov ax, 8
sub ax, 3


Now I want to multiply by 2...


shl ax, 1


Or was I "supposed" to use "mul" there? As Baldr points out, "mul" (and "div") silently use dx. Is this a "trick question"? Well, an 8-bit "mul" or "div" don't use dx. Is that what we're "supposed" to do? With just ax, bp, and sp to use (in dos, interrupts use "our" stack, so sp isn't really useable!) we haven't got a spare 8-bit register. We could use an 8-bit memory location... Although the stack has a 16-bit "size" in 16-bit code, we can perfectly well access an 8-bit location on it, though not with "push" and "pop". Given the registers specified, and the word "stack" in the topic, I suspect you're "supposed" to create a "stack frame" with some "local variables" on it, in which to store some temporary results. I'm not sure whether using 8-bit operations in order to avoid "silently" using dx is "silently" part of the assignment, or not. These "given" numbers will all fit in a byte, but that might not be the "general" case.

A very "general" case would be to let the user input "10 * 4 / 2 + ... whatever", allowing arbitrary operators and arbitrary levels of parentheses, "parse" it and calculate it. If you suspect that next week's assignment is going to be something like that, it may influence how you approach this assignment! :)

You'll need to know/decide how large numbers you need to handle, and what, if anything, you want to do about overflow. Do you need to handle negative inputs/results? The "given" numbers are easy, but what other "given" numbers should the code handle?

You can probably guess how you're "supposed" to do this by "where you are" in the course. Or "you can find out a lot, just by askin'"... Your code so far looks like you want "local variables" on the stack. Perhaps something like...


org 100h
section .text
    push bp ; for no good reason but that it's "standard"
    mov bp, sp ; establish a "stack frame pointer"
    sub sp, 8 ; enough for 4 words or 8 bytes - more than we need

; we can give our variables names...
%define tmp1 bp - 2
%define tmp2 bp - 4
%define tmp3 bp - 6
%define tmp4 bp - 8

    mov ax, 8
    sub ax, 3

; though "tmp1" has room for a word, we can use just a byte
    mov byte , 2
    mul byte ; al * -> ax

; use the whole 16 bits here
    mov , ax

; now do the first part
    mov ax, 10
    mov byte , 4
    mul byte
    mov byte , 5
    div byte
; oh, oh! the "given" numbers divide evenly, if there
; had been a remainder, it would be in ah. use it to round?
; throw it away? are we "supposed" to use ah?
; maybe we would have been better off with words - ignore dx?
; no? okay, use ax, and throw away any remainder:
    and ax, 0FFh ; there!

    add ax,

; are we done? destroy stack frame:
    mov sp, bp
    pop bp
    ret ; just to prove we can...

; better?
; mov ah, 4Ch
; int 21h
; return result in al as errorlevel?

%undef tmp1
; etc. - if you want to be able to reuse them



That's untested - I don't even know if it'll assemble - or gives correct results - or if it's anything like the way you're "supposed" to do it, but it's an attempt to use "mul" and "div" without using dx. Another possibility would be to use words throughout, and avoid "mul" and "div"... our two multiplies can both be replaced with shifts, and "div" can be replaced by repeated subtraction ("div" is so slow that subtraction is sometimes faster!!!) If the next set of "given" numbers can't be multiplied by shifts... back to "mul"... or do repeated "add"s... Easiest thing would be to use dx without sayin' so - but that depends on if the assignment is a "trick question". Use your judgement.

Best,
Frank

Posted on 2010-04-25 16:57:54 by fbkotler
i compiled your code and obtained 12 as result which is not suppose to be the correct answer.How can i perform the operation 10*4/5 cos when i mov into bp after doing mov ax 10 and imul ax, 4 i obtain the 8 as result which is correct... but the problem is adding the two parts together to obtain 18.. i`ve been working on this for two days already need help please!!!!!!
Posted on 2010-04-25 18:37:03 by foxynash
thanks bald and frank i just realised wafter a last trial that 18 is in binary and in hex its 12 which is correct answer thanks......
Posted on 2010-04-25 18:58:44 by foxynash
I'm posting this only because it use the stack a bit less.

org 0x100
; Compute b*c/d+(e-f)*g
      mov      bp, sp

; We are going to compute b*c/d first
      mov      ax,
      imul    ax,
      cwd ; Ensures DX will be either 0 or -1 but not any garbage that would make the division fail. (Not always needed but I'm assuming DX is in an unknown state at this point)
      idiv   

; We save AX
      push    ax

; We are going to compute (e-f)*g now
      mov      ax,
      sub      ax,
      imul    ax,

; Now we add up the two parts to complete the computation
      add      ax,
      mov      sp, bp ; Just to restore SP to the value previous to "PUSH AX" (in this code not really needed)

; Trap to see results in the debugger (use DEBUG here or whatever you like)
      int3

      int      0x20

; I'll use integer variables to pretend flexibility on the values at run-time (them could have been all equates/constants and in such case the square brackets in the instructions must be removed)
b dw 10
c dw  4
d dw  5
e dw  8
f dw  3
g dw  2

I've used fasm, but I believe it also compiles in NASM and in TASM probably it requires some minor changes.
Posted on 2010-04-25 20:48:58 by LocoDelAssembly
I'm posting this only because it don't use anything besides ax (ip/flags, of course).


        org    100h
        mov    ax, 10 shl 8
        aad    4
        aam    5
        mov    al, 8
        sub    al, 3
        xchg    ah, al
        aad    2
        ret


Immediate power! ;-)
Posted on 2010-04-26 11:46:57 by baldr
Wow!!! That definitely wins the prize for "coolest code"!

(Nasm knows "shl" as an instruction, but not an operator - that'll have to be changed to "<<" for Nasm to eat it)

A couple extra instructions will return the answer as an exitcode - in Linux, we can just do "echo $?" to see the exitcode of the last program that ran - in decimal, so we don't get confused. :) I don't think that works in dos, but a few extra instructions would display the answer...


...
aam 10
add ax, 3030h ; '0' '0' - to convert number to character
xchg al, ah
int 29h
xchg al, ah
int 29h

ret


(this little trick only works for two-digit numbers)

Cool as this code is, I think LocoDelAs has posted a more "appropriate" approach for Foxynash to follow. Putting the "given numbers" in variables is a lot more flexible than "hard coding" them... a step towards allowing the user to enter values (or reading them from a file)... in turn, a step towards "arbitrary operations" (tougher, but not that tough). Hard-coding a specific set of "given numbers" is a good first step toward learning to do calculations, but isn't that useful. So, might as well code it in an "expandable" way.

Best,
Frank

Posted on 2010-04-27 20:15:49 by fbkotler

Wow!!! That definitely wins the prize for "coolest code"!


That's how we did it in the 80s.
These days it's VERY SLOW code, as all that BCD-related junk in the instructionset is implemented in slow microcode macros. The x86 instructionset is NOT what a modern x86 CPU implements in hardware. It is a RISC CPU that only implements the common subset of x86 instructions in hardware.
Posted on 2010-04-28 02:53:03 by Scali

These days it's VERY SLOW code, as all that BCD-related junk in the instructionset is implemented in slow microcode macros.


Can't imagine why they eliminated it in Long Mode :lol:
Posted on 2010-04-28 03:17:33 by SpooK
Just for the sake of argument, what's your "fast" implementation, Scali?

The reason I ask is not that I doubt your assertion, but... I once set out to determine "How slow *is* it?"... I was interested in "das" in particular... and my results were "highly inconclusive". I wrote a little "timing harness" - it gives some "odd" results, but usually a definite number of cycles for an instruction or group of instructions ... But "das" was all over the place! I'll post my code - maybe someone can spot something wrong with it... But I think I'll start a new thread... These are not the instructions Foxynash wants, for reasons besides speed (I think it's "undocumented" that some of 'em take operands, isn't it?). Best to hand in code that you can explain, if asked, and I doubt if the class has gotten to those "adjust" instructions... unless you're working alphabetically...

Foolish question, I suppose, what's the fastest way to do "mov ax, 18"... but it raises some other "interesting" questions, in my mind...

Later,
Frank

Posted on 2010-04-28 05:56:06 by fbkotler

Just for the sake of argument, what's your "fast" implementation, Scali?


I'm rather busy with my other projects at the moment, but perhaps you can make a new 'small challenge' topic, so all the members can try their hand at writing the fastest implementation, and we can compare with f0dder's yodel framework, like we did with Homer's challenge a while ago.
I believe these slow instructions are well-documented in both AMD's and Intel's optimization manuals though.
Posted on 2010-04-28 06:06:03 by Scali
need code for implementation of prim`s algorithm to find minimum spanning tree in parallel using multiple threads.... using c++
  I am  a newbie in threads and don`t really know where to start to slove this problem... Can anyone help me on this??/
Posted on 2010-12-01 05:44:01 by foxynash