1

I have to create a small program which carries out the formula and gives the right answer using assembler language with EMU8086 microprocessor emulator. I coded it, there were some errors, I succeed to fix them but the answer which it gives is not correct. I spent a lot of time trying to solve this problem, but unfortunately, unsuccessfully. I need help.

Formula:

y = |x+b|                        if c = a*x

y = a^2 - 3*b                    if c < a*x

y = ] (2*c-a) / (c+a*x) [        if c > a*x

][ - means bring out only whole number not remnant.

Set variables:

a=3
b=4
c=6
array  x[] = 2,3,1,4,5
array  y[] is the answers

So this is the basic point. Here it counts multiplication of a*x and compares the result with variable c. Depending on result it should switch to different calculations.

cikl:      ; cycle starts 
      XOR dx,dx   
      MOV bx,a ; bx=a           
      MOV al,x[si]
      XOR ah,ah
      MUL bx;
      JC kl1; overflow
      CMP ax,0 ; compare ax with 0    
      JB f2   ; if a*x < 0 jump to f2  
      JA f3   ; if a*x > 0 jump to f3

So it should give me this result like this:

x=2 y=6
x=3 y=-3 (overflow error should be here)
x=1 y=1
x=4 y=8
x=5 y=9

But currently it prints this: screenshot

Code:

; task:  | x+b |                        if c= a*x
;        a^2 - 3*b                      if c< a*x
;        ] ( 2c-a ) / ( c+ax ) [        if c> a*x 
;        a=DW b=DB c=DB x=DB y=DW
;

stekas  SEGMENT STACK
DB 256 DUP(0)
stekas  ENDS

duom    SEGMENT
a DW 3;
b DB 4;
c DB 6;
x DB 2,3,1,4,5
kiek = ($-x);
y DW kiek dub(0AAh)
isvb    DB 'x=',6 dup (?), ' y=',6 dup (?), 0Dh, 0Ah, '$'
perp    DB 'Perpildymas', 0Dh, 0Ah, '$'
daln    DB 'Dalyba is nulio', 0Dh, 0Ah, '$'
netb    DB 'Netelpa i baita', 0Dh, 0Ah, '$'
spausk  DB 'Skaiciavimas baigtas, spausk bet kuri klavisa,', 0Dh, 0Ah, '$'     
duom    ENDS

prog    SEGMENT
assume ss:stekas, ds:duom, cs:prog
pr:
  MOV ax, duom ;move data to ax
  MOV ds,ax
  XOR si,si   ; si=0
  XOR di,di   ; di = 0; 
  MOV cx,kiek ; cx = kiek
  JCXZ pab   ; if kiek = 0 jump to the end 
cikl:      ; cycle starts 
  XOR dx,dx   
  MOV bx,a ; bx=a           
  MOV al,x[si]
  XOR ah,ah
  MUL bx;
  JC kl1; overflow
  CMP ax,0 ; compare ax with 0    
  JB f2   ; if a*x < 0 jump to f2  
  JA f3   ; if a*x > 0 jump to f3

; part of task:  | x+b |                 if c= a*x    
f1:                     
  MOV al, b
  MOV dl, x[si]
  ADD al, x[si]
  JC kl1
  JMP re

;            a^2 - 3*b               if c< a*x  
f2:
  MOV ax, a
  XOR ah, ah
  MOV bl, al
  MUL bl
  JC kl1; overflow
  MOV dx, ax
  XOR ax, ax
  XOR bl, bl
  MOV bl, 3
  MOV al, b
  XOR ah, ah
  MUL bl
  JC kl1; overflow
  SUB dx, ax
  XOR ax, ax
  MOV ax, dx
  JMP re 
;            ] ( 2c-a ) / ( c+ax ) [ if c> a*x   
f3:
 MOV al, c
 XOR ah, ah
 MOV dl, 2
 MUL dl
 JC kl1; overflow
 XOR dl, dl
 MOV dx, a
 SUB ax, dx
 CMP ax, 0
 JE kl2; number can be only positive
 XOR dl, dl
 MOV bx, ax
 XOR ax, ax 
 MOV dx, a ; dx=a           
 MOV al, x[si]
 XOR ah, ah
 MUL dx;
 JC kl1;overflow
 XOR dx, dx
 MOV dl, c
 ADD ax, dx
 JC kl1;overflow
 MOV dx, ax
 MOV ax, bx
 MOV bx, dx
 XOR dx, dx
 DIV bx
 JC kl1
 XOR ah, ah
re:
CMP ax, 0     ;does result fit
JE ger
JMP kl3
ger:    
MOV y[di], ax
INC si
;INC si
;INC di 
INC di
LOOP cikl
pab:
;bring out results to screen
;============================
XOR si, si
XOR di, di
MOV cx, kiek
JCXZ is_pab
is_cikl: 
MOV al, x[si]  ; number x is in ax reg. 
XOR ah,ah
PUSH ax
MOV bx, offset isvb+2
PUSH bx
CALL binasc
MOV ax, y[di]
;XOR ah, ah        ; number y is in ax reg.
PUSH ax
MOV bx, offset isvb+11
PUSH bx
CALL binasc

MOV dx, offset isvb
MOV ah, 9h
INT 21h
;============================
INC si
;INC si
iNC di   
;INC di
LOOP is_cikl
is_pab:
;===== PAUSE ===================
;===== press any key ===
LEA dx, spausk
MOV ah, 9
INT 21h
MOV ah, 0
INT 16h
;============================
MOV ah, 4Ch   ; program ends, come back to OS
INT 21h
;============================

kl1:    LEA dx, perp
MOV ah, 9
INT 21h
XOR al, al
JMP ger
kl2:    LEA dx, daln
MOV ah, 9
INT 21h
XOR al, al
JMP ger
kl3:    LEA dx, netb
MOV ah, 9
INT 21h
XOR al, al
JMP ger

; convert number to decimal and save
; ASCII kode. Parametrai perduodami per steka 
; in ASCII code. Parameters pass through stack
; Fist parameter ([bp+6])- converted number
; Second parameter ([bp+4])- place for result

binasc    PROC NEAR
PUSH bp
MOV bp, sp
; saving used registers
PUSHA
; Filling line with spaces
MOV cx, 6
MOV bx, [bp+4] 
tarp:    MOV byte ptr[bx], ' '
INC bx
LOOP tarp
; number is prepared for DIV is 10
MOV ax, [bp+6]
MOV si, 10
val:    XOR dx, dx
DIV si
;  remnant to ASCII code
ADD dx, '0'   ; can be--> ADD dx, 30h
;  write number to the end of the line
DEC bx
MOV [bx], dl
; count number of converted symbols
INC cx
; do we need to DIV more ?
CMP ax, 0
JNZ val

POPA
POP bp
RET
binasc    ENDP
prog    ENDS
END pr
David
  • 21
  • 2
  • Use your emulator to single step the code and see where it goes wrong. Also, specify inputs, expected and actual output for the case when it doesn't work. – Jester Nov 01 '17 at 16:20
  • 2
    You say, "the answer which it gives is not correct," but you don't say what you expect the answer to be. I'd suggest editing your question to include that, as well as any additional information about what *does* work, and what, specifically, *doesn't*. I'm not sure how easy this is to do with Assembler, but consider reducing the amount of code, and creating a [minimal, complete and verifiable example](https://stackoverflow.com/help/mcve), which might help you find the answer yourself, and, if not, will certainly help others to help you. – DaveyDaveDave Nov 01 '17 at 16:31
  • Thank you for trying to help. Question updated. I made some progress and now one of the answers from y arrays is correct, but others are wrong. Currently case of y = ] (2*c-a) / (c+a*x) [ if c > a*x gives the right answer which is: when y=1 x=1 – David Nov 01 '17 at 17:43
  • The problem occurs somewhere after calculations where the process: " re: " starts. I think the result ax is not correctly written to y[ di ] (moved to memory). Because after changing "CMP ax, 0" to "CMP ah, 0" in "re:" part of code all answer changed. But now only one of them is correct. – David Nov 01 '17 at 17:52
  • 2
    You have your emulator. Keep single stepping and **verify** each instruction is doing what you expect it to. It should be easy to spot the error. Also I have no idea what you want to do with `cmp ax, 0`. You should use better labels and comments. `XOR ax, ax; MOV ax, dx` makes no sense either. – Jester Nov 01 '17 at 18:02
  • Still missing the "minimal" part of MCVE. Boil this down to something much smaller which still doesn't do what you want. – Peter Cordes Nov 01 '17 at 18:06

1 Answers1

3

In assembly, no number is ever BELOW zero and so your program will never jump to f2.

CMP ax,0 ; compare ax with 0    
JB f2   ; if a*x < 0 jump to f2  
JA f3   ; if a*x > 0 jump to f3

You want to have 3 different outcomes depending on Sign(a*x).
In order to achieve that you need to treat the product in a*x as a signed number. In assembly programming you do this by using the signed versions of the conditional jumps (jl, jg, ...). You've used the unsigned versions instead (jb, ja, ...).

CMP ax,0 ; compare ax with 0    
JL f2   ; if a*x < 0 jump to f2  
JG f3   ; if a*x > 0 jump to f3

The division does not define any flags.

 XOR dx, dx
 DIV bx
 JC kl1
 XOR ah, ah
re:

This JC kl1 will jump based on the current value of the carry flag (CF), but since the DIV instruction leaves all flags undefined, there's no telling what the CF will be at this point in the program. It could be that it is still clear from the preceding xor dx, dx, but that need not always be the case. If INTEL would have documented the DIV instruction to leave the flags unmodified, it would have been the case though.

Bottomline is that your program will behave erratically.

Fifoernik
  • 9,411
  • 1
  • 18
  • 26
  • 1
    Worse, more likely your program will behave the same every time on *your* CPU, but could run differently for someone else on a different CPU. And BTW, @David:[`test ax,ax` would be shorter than `cmp` but do the same thing](https://stackoverflow.com/questions/33721204/test-whether-a-register-is-zero-with-cmp-reg-0-vs-or-reg-reg/33724806#33724806). – Peter Cordes Nov 02 '17 at 17:04