Page 1 of 2

Clock troubles [Fixed]

Posted: Wed May 07, 2008 12:26 am
by chezzestix
Well this is my first peice of ASM that just epically fails. It doesnt output a single thing under Virtual Box which is odd since Im just implementing Int 10:0Eh, which has worked every other use, and Int 1A:02h, which has also worked on previous occasion. Any thoughts?

*1 http://lrs.uni-passau.de/support/doc/in ... B-2209.HTM
*2 http://lrs.uni-passau.de/support/doc/in ... B-0090.HTM

I use nasm to compile the code and then paste it into my disk template that I've been using while I learn to write my own. Previous versions have been written by me in straight hex but nasm gets it done in smaller amounts of space. I then adjust any jmps that need it.

Maybe someone can test this on another emulator or just by looking at the hex/asm you know what is going on.

Posted: Wed May 07, 2008 4:09 am
by Combuster
Use comments. This is plain unreadable

Posted: Wed May 07, 2008 4:24 am
by JamesM
I particularly like* the hardcoded jmp instead of using a label... :evil:

Posted: Wed May 07, 2008 4:51 am
by JackScott
It's quite obvious what this code wants to do: print "I R HARDCORE" to video memory. :P

Posted: Wed May 07, 2008 7:27 am
by chezzestix
Sorry about that guys, with all the "hardcoring" :P I've been doing lately I've forgotten good practice.

Im not totally versed in x86 asm, did a similar variant a year or so back, so I dont want to create the whole file using it and I'm pretty sure a lable wouldnt move so well in a copy paste but then again I'm a noob. Feel free to rebuke me if I'm wrong. However, is there anything wrong with "hardcoded jump" if the project is this small?

The code has been commented, excuse me if I'm holding hands a little bit here with the comments.

Posted: Wed May 07, 2008 10:47 am
by Combuster
Oh well, some new remarks:
1) What are the segment registers pointing to?
2) Hardcoded jumps to a potentially changing address are absolutely bad practice.
3) you're probably overwriting your code during execution

Posted: Wed May 07, 2008 11:54 am
by bewing
4) Your divide opcodes aren't going to work, because you didn't set dx to 0 before each division.

Posted: Mon May 12, 2008 4:08 am
by chezzestix
Hymmm... well atleast this new code doesnt instantly shut down the machine but it doesnt output anything either plus its "functionized" for readability. Correct me if I'm wrong but I'm assuming by using an 8bit register I dont have to worry about dx when I use div anymore.

Also:
Can someone clear up the difference between jmp and call?

Posted: Mon May 12, 2008 4:59 am
by AJ
chezzestix wrote:Also:
Can someone clear up the difference between jmp and call?
Call pushes a return value on to the stack and transfers control (can be used with ret), jmp transfers control but does not push a return value on to the stack, so you can't use ret.

Cheers,
Adam

Posted: Mon May 12, 2008 5:17 am
by chezzestix
Thank you, code is updated but the problem still exists. Any thoughts?

Also, does anyone know of a good debugger? I've looked around but all of them want .exes. This would be a tad easier to figure out if I could take a gander at whats going on.

Posted: Mon May 12, 2008 8:52 am
by Dex
Try
time.asm

Code: Select all

org 100h
segment .text
   mov ah,01h         ; from here to
   mov cx,2000h       ; ,,,,,,,,,,,,,
   int 10h            ; here, hide's cursor(bios int's)
m0:
   mov ah,2     ; get's the (bios int's)
   int 1ah      ; time in BCD , dl=0
   push cx
   push dx
   pop eax
m1:
   mov al,163
   sub dl,160   ; gives c,c,nc,c,c,nc,c,nc+z
   ja $+3      ;       h h :  m m  : s  s
   rol eax,4    ; if jump is taken, we're in the middle of this.

   push  ax
   mov ah,0eh
   int 10h

   pop  ax

   jne m1
   mov al,13   ; CR to re-position cursor - looks crappy.
   mov ah,0eh
   int 10h

 ;  mov ah,1     ; until key is pressed
 ;  int 16h
 ;  jz m0

   mov ah,01h         ; here to
   mov cx,0d0eh       ; ,,,,,,,,
   int 10h            ; here show cursor (bios int's)
   ret

Or for date

Code: Select all

; nasm -f bin -o date.com date.asm
org 100h
segment .text
       call getdate           ; getdate
       xor  ah,ah
       int  16h

     ;  mov  ax,4c00h
     ;  int  21h
       ret
getdate:                ;start of getdate

       mov  ah,04h                  ;get date from CMOS
       int  1ah                     ;invoke interrupt to get date
       push cx
       push dx
       mov  al,dl                   ;get day
       call convert                 ;convert day BCD to ASCII
       call display_date            ;display day
       pop  dx
       mov  al,dh                   ;get month

       call convert                 ;convert month BCD to ASCII
       call display_date            ;display mouth
       pop  cx
       mov  al,cl                   ;get year

       call convert                 ;convert year BCD to ASCII
       mov  si, val
       call putstr                  ;invoke print proc to display
       ret

convert:                            ;start of convert
       mov  ah,al                   ;copy AL to AH
       and  ax,0f00fh               ;mask bits
       mov  cl,4                    ;CL=04 for shift
       shr  ah,cl                   ;shift right AH to get unpacked BCD
       or   ax, 3030h               ;combine with 30 to get ASCII
       xchg ah,al                   ;swap for ASCII storage convention
       mov  [val],ax                ;store the ASCII value in VAL 
       ret

display_date:                       ;start of display_date
       mov  si,val
       call putstr
       mov  ah,0eh                 ;display / to seperate months, days, and years
       mov  al,'/'
       int  10h
       ret

putstr:     ; SI = address of string to display
       lodsb
       or  al,al ;
       jz  putstrd
       mov ah,0eh
       mov bx,0007h
       int 10h                          ; print char
       jmp  putstr
putstrd:
       ret
segment .data

val dw 0,0



Posted: Mon May 12, 2008 10:03 am
by edfed

Code: Select all

start: 
mov dx,0 
mov si,0 
mov di,0 
call gettime 
call strtime 
mov ecx,3 
mov bh,0Ah 
loop0: 
call bcd2ascii 
loop loop0 
mov bh,0 
call asciiout 
call colonout 
call asciiout 
call colonout 
call asciiout 
call crout 
call start
this code cannot work well.

stack overflow due to the call start.
replace with jmp start.

Posted: Mon May 12, 2008 10:32 am
by Schol-R-LEA
AJ wrote:
chezzestix wrote:Also:
Can someone clear up the difference between jmp and call?
Call pushes a return value on to the stack and transfers control (can be used with ret), jmp transfers control but does not push a return value on to the stack, so you can't use ret.
There is also a difference in the purpose of the two, which is the reason for the different behavior.

JMP is a general, unconditional transfer of control, like a GO TO in a higher-level language; all it does is change the value of the instruction pointer. It is generally used for flow control within a subroutine.

CALL, on the other hand, is intended for, well, calling subroutines. Its purpose is to let you jump to another section of code, perform a set of operations, and then automatically return to the instruction after the CALL, without explicitly knowing where the call itself was. To do this, it pushes the return value onto the stack. The RET instruction reverses this, by popping an address off of the stack and jumping to it.

Note that these two instructions are independent of each other and not in any way, shape or form guaranteed to work. One of the reasons stack discipline is important is because the RET has no way of confirming that the value it is popping off the stack is in fact the correct one - it has to assume that the stack pointer is in the right position, and if it isn't, the program will jump into the Featureless Void. The subroutine has to make sure that, when it is finished, the stack has been restored to the status quo ante before it returns - not just holding the right value, but in the same exact position, because the calling function also has to be able to find its own stack frame afterwards. This can get complicated by the use of stack for arguments and local variables, but the basic issue remains that the subroutine needs to restore the stack.

There are a number of tricks which can be used to take advantage of this, but they are anything but safe. Many exploits are based on this sort of thing, actually, and if you are messing about on the stack, chances someone else will take advantage of it as well. In general, the rule is, keep your stack frames clean.

The wiki has a lot of material on assembly programming, so you may want to take a look. The section on calling conventions is specifically relevant; while you don't need to follow the C conventions if you are writing a stand-alone assembly program, it is often useful to do so, and knowing them helps make a lot of things about both assembly and C clearer.

Posted: Tue May 13, 2008 1:31 pm
by bewing
As said above, the last line of your main section should say JMP start.

But the reason you aren't getting any output is that all your output routines say INT 10 -- when they should say either INT 10h, or INT 0x10 -- so you are calling the wrong BIOS function to try to do your actual output.

Posted: Tue May 13, 2008 8:43 pm
by chezzestix
That couldnt have been good either.. silly typos... but the code wasnt getting that far. I started placing some custom break points in the code*1 until I found the point at which the program would keil over. I put one break point before the "div bh" in the bcd2ascii function and one after and the computer locks up before the second one is reached.

Whats wrong with my div command?