Recent Posts

Pages: 1 ... 6 7 [8] 9 10
71
Using NASM / Extracting 16-bit value without using a 32-bit register
« Last post by mik3ca on January 31, 2021, 07:03:01 PM »
I'm trying to figure out how to work with 16-bit values in 32-bit spaces because some functions need to use the space as 32-bit but I only use 16-bit numbers.

In this code example, we assume I'm calling DOS interrupt 2Fh with function 0 (AX=0) and we assume function treats the internal 32-bit value aval as a size to a string (for example).

The values I want to use are all 16-bit so I want to be able to load a 16-bit value in and retrieve a 16-bit value from the same variable after the interrupt is executed.

The safest approach is with the code below:

Code: [Select]
myfunction:
    xor EAX,EAX
    mov AX,CX
    mov [CS:aval],EAX
    xor AX,AX
    int 2Fh
    mov EAX,[CS:aval]
    mov CX,AX
ret

aval dd 0h  ;32-bit storage space that an interrupt requires
                     ;because interrupt checks ALL 32 bits, not just part.

I thought of replacing the above with one of these fragments, but the endianness of the intel processors sometimes confuse me because in some instances, values are stored backwards.

Here's idea 1 of shorter code:

Code: [Select]
myfunction:
    mov [CS:aval],CX
    xor AX,AX
    int 2Fh
    mov CX,[CS:aval]
ret

aval dd 0h

Here's idea 2 of shorter code:

Code: [Select]
myfunction:
    mov [CS:aval+2],CX
    xor AX,AX
    int 2Fh
    mov CX,[CS:aval+2]
ret

aval dd 0h

So which of my 2 ideas would work best? or is there a better idea? This code fragment will be part of an MS-DOS COM file when compiled.
72
Code: [Select]
test  ax,ax
setnz al  ; 386+ instruction.
xor   ah,ah
73
Programming with NASM / Smallest code/cpu consuming function to get 1 of 2 values
« Last post by mik3ca on January 30, 2021, 06:22:32 AM »
I have an input to my program (Let's call it AX here) which can be loaded with any value, but the program only works with two values from AX. 0 and 1. So if the input is anything but a zero, then a 1 is returned. This is the code I have so far:

Code: [Select]
cmp AX,0h
  je nzero
    mov AX,1h
  nzero:

Well, I don't have to exactly have '1' as the other value, but in the end I want AX to be one of two values, at least one of them being zero.

Is there a way to crunch my code down without having to do a comparison followed by potential jump?
74
Example Code / Re: Accepting keyboard input to implement 'Password' program
« Last post by S Mahen on January 30, 2021, 01:42:29 AM »
Thank you so much for the sample code... I am modifying the same as per problem statement. Will share the modified code...
75
Programming with NASM / Re: 2 Stage Bootloader
« Last post by timryazthunder on January 29, 2021, 08:35:44 PM »
Tried to make an OS using the two stage CD bootloader and it miserably fails whenever the system is trying to read from BIOS,
Used 86Box as an emulator.
Throws up every time with a sector error.
It shows the same message as that anonymous coder with the CD boot.
76
Example Code / Re: Accepting keyboard input to implement 'Password' program
« Last post by fredericopissarra on January 29, 2021, 01:59:18 PM »
Hi,
Now I want to work on 64-bit code.
Using syscall "ioctl" (16).

Here's the same excellent code from Gunner, but for x86-64 (with tiny corrections):
Code: [Select]
  bits        64
  default     rel

ICANON      equ 1<<1
ECHO        equ 1<<3

; NOTE: syscalls #s are different for SysV x86-64 ABI.
sys_exit    equ 60
sys_read    equ 0
sys_write   equ 1
sys_ioctl   equ 16
stdin       equ 0
stdout      equ 1

  ; CHANGE: don't need to keep these bytes in a writable section!
  section .rodata

szAsterisk  db  "*"
szLF        db  `\n`

  ; NOTE: Beware that .bss isn't zeroed automatically, as in C.
  section     .bss

lpBufIn     resb    2
lpPassIn    resb    24
termios     resb    36

  section .text

  global _start
_start:
  call    echo_off
  call    canonical_off

  ; NOTE: Changed from edi to ebx because SysV ABI for x86-64 uses RSI.
  xor     ebx, ebx
.GetCode:   
  cmp     ebx, 24
  je      .PassTooBig
   
  call    GetKeyCode

  mov     al, byte [lpBufIn]
  cmp     al, "Q"
  je      .Done
  cmp     al, 10
  je      .Continue

  mov     byte [lpPassIn + rbx], al
  call    PrintAsterisk
  inc     ebx
  jmp     .GetCode
 
.Continue:
  mov     byte [lpPassIn + rbx], 0    ; FIX
   
  ;~ for testing purposes
  ;~ #####################################
  inc ebx                             ;~ #
                                      ;~ #
  mov     edx, 1                      ;~ #
  lea     rsi, [szLF]                 ;~ #
  mov     eax, sys_write              ;~ #
  mov     esi, stdout                 ;~ #
  syscall                             ;~ #
                                      ;~ #
  mov     edx, ebx                    ;~ #
  lea     rsi, [lpPassIn]             ;~ #
  mov     eax, sys_write              ;~ #   
  mov     esi, stdout                 ;~ #
  syscall                             ;~ #
  ;~ #####################################
       
  ;~ Compare passowrds here!!!
  jmp     .Done
   
.PassTooBig:
  ;~ Entered password too big!
   
.Done:
  call    echo_on
  call    canonical_on

  mov     eax, sys_exit
  xor     edi, edi
  syscall
   
;~ #########################################
GetKeyCode:
  mov     eax, sys_read
  mov     edi, stdin
  lea     rsi, [lpBufIn]
  mov     edx, 1
  syscall
  ret
 
;~ #########################################
PrintAsterisk:
  mov     edx, 1
  lea     rsi, [szAsterisk]
  mov     eax, sys_write
  mov     edi, stdout
  syscall     
  ret        
   
;~ #########################################
canonical_off:
  call read_stdin_termios

  ; clear canonical bit in local mode flags
  and dword [termios+12], ~ICANON

  call write_stdin_termios
  ret
     
;~ #########################################
echo_off:
  call read_stdin_termios

  ; clear echo bit in local mode flags
  and dword [termios+12], ~ECHO

  call write_stdin_termios
  ret

;~ #########################################
canonical_on:
  call read_stdin_termios

  ; set canonical bit in local mode flags
  or dword [termios+12], ICANON

  call write_stdin_termios
  ret

;~ #########################################
echo_on:
  call read_stdin_termios

  ; set echo bit in local mode flags
  or dword [termios+12], ECHO

  call write_stdin_termios
  ret

;~ #########################################
read_stdin_termios:
  mov eax, sys_ioctl
  mov edi, stdin
  mov esi, 0x5401
  lea rdx, [termios]
  syscall
  ret

;~ #########################################
write_stdin_termios:
  mov eax, sys_ioctl
  mov edi, stdin
  mov esi, 0x5402
  lea rdx, [termios]
  syscall
  ret
77
Example Code / Re: Accepting keyboard input to implement 'Password' program
« Last post by S Mahen on January 29, 2021, 12:41:04 AM »
Hi,
Now I want to work on 64-bit code.
Using syscall "ioctl" (16).

The objective is same...

Please guide me.
78
Programming with NASM / Re: 16-bit Timer tick function
« Last post by fredericopissarra on January 27, 2021, 04:17:58 PM »
Why not capture interrupt 0x1C instead?
79
Programming with NASM / 16-bit Timer tick function
« Last post by mik3ca on January 26, 2021, 09:03:30 PM »
I'm rewriting parts of my code from Qbasic to assembler because I'm making a server that gives me the best speed for CPU.

Anyways, I'm having trouble with the timer function.

I'm using interrupt 1Ah with AH=0 to receive clock ticks. Info for that is here: http://www.ctyme.com/intr/rb-2271.htm

For this code, ES:DI is the segment and offset to a predefined structure in QuickBasic that's passed in through "Call absolute".

For those that don't care about QuickBasic, don't worry because the code I'm showing has everything commented

Code: [Select]

;These are offsets to individual elements in the QuickBasic struct
func equ 0h
errc equ 2h
tmo equ 4h
debug equ 6h


;Function begins
atimer:
  xor AX,AX ;Set AH+AL to 0
  mov [ES:DI+tmo],AX ;Set member tmo of struct to 0.
  int 1Ah ;Call timer tick interrupt
  cmp AL,0h ;do clock read again if 12am marker set
  je noclk2
    xor AX,AX ;Set AH+AL to 0 for second call
    int 1Ah ;Call timer tick interrupt since midnight passed
  noclk2:
;We will store timer value as EAX instead of the returned CX:DX
  xor EAX,EAX  ;Set EAX to 0
  mov AX,CX ;Set lower 16-bits to CX
  shl EAX,16 ;make those 16-bits as high 16-bits
  mov AX,DX ;Set lower 16-bits to DX
  mov EBX,[CS:myclock] ;Load old clock value as EBX
  mov [CS:myclock],EAX ;Save new clock value
  mov DX,[CS:myclockinit] ;Load initialized value to DX
  cmp DX,0h ;See if function was called before
  je tosmlc
  sub EAX,EBX ;this clock function was called so subtract timer values
  jc tosmlc ;if value is under 0 then 1 second didnt pass
    cmp EAX,19 ;See if we got 19 ticks (18.2 ticks a sec)
    jl tosmlc
    inc word[ES:DI+tmo] ;we have so we set tmo member of struct to 1
  tosmlc:
  mov DX,1h ;Set clock function to 1 so next time we call it we can check for timeout
  mov [CS:myclockinit],DX
jmp endit ;do ending and return to Qbasic

myclock dd 0 ;This stores the last time value read from the interrupt
myclockinit dw 0 ;If non-zero, it means function was executed at least once


Now the odd thing is that when I run the code the first time, the timeout value is correct and things work as expected. However when I run it the second time, I receive this error:

Code: [Select]
DOS memory-arena error

Then QuickBasic crashed and I'm returned to DOS with the DOS prompt appearing right after the error message (with no space after the word error) and no blinking cursor after the prompt.

So I'm wondering what I may be doing wrong.

Could it be that my math is incorrect?

Could it be that the interrupt function I'm using is not functional? Maybe I discovered a bug with DOSBOX that I'm not aware of? I'm using DOSBOX 0.74 for testing.

Could it be that the source of interrupt information I refer to is not correct?

What would be a fast and working method to calculate a 1-second timeout?

I ask here because I notice when I use some quickbasic functions, they are slower than their assembler counterparts.
80
Example Code / Re: My own 64-bit `puts' instruction (No length required)
« Last post by MediocreVeg1 on January 19, 2021, 05:27:09 PM »
Quote
I confesss I cannot see how it works, too...  ;)
Yeah, I think I'll change my thing to your not solution so I at least understand what is going on.

And about the registers, I think I finally get it now. Thanks for all the help!
Pages: 1 ... 6 7 [8] 9 10