Duda ensamblador

Todo sobre la creación, diseño y programación de nuevo software para
nuestro Spectrum

Moderador: Sir Cilve Sinclair

Responder
K.O.D.
Jack The Nipper
Mensajes: 115
Registrado: Mar Sep 30, 2008 8:45 am
Ubicación: Valencia

Duda ensamblador

Mensaje por K.O.D. » Jue Dic 31, 2015 12:47 am

Hola, un saludo. No tengo mucha idea de ensamblador, eso vaya por delante: estaba haciendo un programilla que es simplemente una llamada a la rutina DOS_ESPACIO del plus 3, la idea es que devuelva el espacio libre en disco y que lo pueda leer desde BASIC, empleando como esqueleto el ejemplo de llamada a DOS_CATALOGO que proporciona el mismo manual del plus 3:

Código: Seleccionar todo

     org  28672

mystak       equ 40959  ;arbitrary value picked to be below BFE0h and above 4000h
staksto      equ 36864  ;somewhere to put BASIC's stack pointer
bankm        equ 23388  ;system variable that holds the last value output to 7FFDh
port1        equ 32765  ;address of ROM/RAM switching port in I/O map
catbuff      equ 32768  ;somewhere for DOS to put its catalog
dos_catalog  equ 286  ;the DOS routine to call

demo:

     di                  ;unwise to switch RAM/ROM without disabling interrupts
     ld   (staksto),sp   ;save BASIC's stack pointer
     ld   bc,port1       ;the horizontal ROM switch/RAM switch I/O address
     ld   a,(bankm)      ;system variable that holds current switch state
     res  4,a            ;move right to left in horizontal ROM switch (3 to 2)
     or   7              ;switch in RAM page 7
     ld   (bankm),a      ;must keep system variable up to date (very important)
     out  (c),a          ;make the switch
     ld   sp,mystak      ;make sure stack is above 4000h and below BFE0h
     ei                  ;interrupts can now be enabled

;
;The above will have switched in the DOS ROM and RAM page 7. The stack has also
;been located in a "safe" position for calling DOS
;
;The following is the code to set up and call DOS CATALOG. This is where your
;own code would be placed.
;

     ld   hl,catbuff     ;somewhere for DOS to put the catalog
     ld   de,catbuff+1   ;
     ld   bc,1024        ;maximum is actually 64x13+13 = 845
     ld   (hl),0
     ldir                ;make sure at least first entry is zeroised
     ld   b,64           ;the number of entries in the buffer
     ld   c,1            ;include system files in the catalog
     ld   de,catbuff     ;the location to be filled with the disk catalog
     ld   hl,stardstar   ;the file name ("*.*")
     call dos_catalog    ;call the DOS entry
     push af             ;save flags and possible error number returned by DOS
     pop  hl
     ld   (dosret),hl    ;put it where it can be seen from BASIC
     ld   c,b            ;move number of files in catalog to low byte of BC
     ld   b,0            ;this will be returned in BASIC by the USR function

;
;If the above worked, then BC holds number of files in catalog, the "catbuff"
;will be filled with the alphanumerically sorted catalog and the carry flag but
;in "dosret" will be set. This will be peeked from BASIC to check if all went
;well.
;
;Having made the call to DOS, it is now necessary to undo the ROM and RAM
;switch and put BASIC's stack back to where it was on entry. The following
;will achieve this.

     di                  ;about to ROM/RAM switch so be careful
     push bc             ;save number of files
     ld   bc,port1       ;I/O address of horizontal ROM/RAM switch
     ld   a,(bankm)      ;get current switch state
     set  4,a            ;move left to right (ROM 2 to ROM 3)
     and  248            ;also want RAM page 0
     ld   (bankm),a      ;update the system variable (very important)
     out  (c),a          ;make the switch
     pop  bc             ;get back the saved number of files in catalog
     ld   sp,(staksto)   ;put BASIC's stack back
     ret                 ;return to BASIC, value in BC is returned to USR

stardstar:

     defb "*.*",255      ;the file name, must be terminated with FFh

dosret:

     defw 0              ;a variable to be peeked from BASIC to see if it worked
Ese es el código original, cambiando hexadecimales por decimales, el pasmo lo ensambla bien. Mi versión para llamar a DOS_ESPACIO elimina lo relacionado con DOS_CATALOGO y deja el resto igual. Se supone que DOS_ESPACIO deja en hl la cifra de Ks libres del disco y nada más, que es lo que quiero poder consultar desde BASIC:

Código: Seleccionar todo

     org  28672

mystak       equ 40959  ;arbitrary value picked to be below BFE0h and above 4000h
staksto      equ 36864  ;somewhere to put BASIC's stack pointer
bankm        equ 23388  ;system variable that holds the last value output to 7FFDh
port1        equ 32765  ;address of ROM/RAM switching port in I/O map
catbuff      equ 32768  ;somewhere for DOS to put its catalog
dos_espacio  equ 289  ;the DOS routine to call

demo:

     di                  ;unwise to switch RAM/ROM without disabling interrupts
     ld   (staksto),sp   ;save BASIC's stack pointer
     ld   bc,port1       ;the horizontal ROM switch/RAM switch I/O address
     ld   a,(bankm)      ;system variable that holds current switch state
     res  4,a            ;move right to left in horizontal ROM switch (3 to 2)
     or   7              ;switch in RAM page 7
     ld   (bankm),a      ;must keep system variable up to date (very important)
     out  (c),a          ;make the switch
     ld   sp,mystak      ;make sure stack is above 4000h and below BFE0h
     ei                  ;interrupts can now be enabled

;
;The above will have switched in the DOS ROM and RAM page 7. The stack has also
;been located in a "safe" position for calling DOS
;
;The following is the code to set up and call DOS CATALOG. This is where your
;own code would be placed.
;

     ld   a,65            ;the disk unit
     call dos_espacio    ;call the DOS entry
     push af             ;save flags and possible error number returned by DOS
     pop  hl
     ld   (dosret),hl    ;put it where it can be seen from BASIC
     ld   hl,0           ;this will be returned in BASIC by the USR function

;
;If the above worked, then BC holds number of files in catalog, the "catbuff"
;will be filled with the alphanumerically sorted catalog and the carry flag but
;in "dosret" will be set. This will be peeked from BASIC to check if all went
;well.
;
;Having made the call to DOS, it is now necessary to undo the ROM and RAM
;switch and put BASIC's stack back to where it was on entry. The following
;will achieve this.

     di                  ;about to ROM/RAM switch so be careful
     push bc             ;save number of files
     ld   bc,port1       ;I/O address of horizontal ROM/RAM switch
     ld   a,(bankm)      ;get current switch state
     set  4,a            ;move left to right (ROM 2 to ROM 3)
     and  248            ;also want RAM page 0
     ld   (bankm),a      ;update the system variable (very important)
     out  (c),a          ;make the switch
     pop  bc             ;get back the saved number of files in catalog
     ld   sp,(staksto)   ;put BASIC's stack back
     ret                 ;return to BASIC, value in BC is returned to USR

stardstar:

     defb "*.*",255      ;the file name, must be terminated with FFh

dosret:

     defw 0              ;a variable to be peeked from BASIC to see if it worked
Sin embargo, una vez ensamblado, si leo desde BASIC el valor devuelto, con LET x=USR 28672, el valor no se corresponde ni guarda relación. ¿Alguien me podría dar una pista?

Un saludo y gracias.

zup
Freddy Hardest
Mensajes: 666
Registrado: Vie Ago 15, 2008 2:43 pm

Re: Duda ensamblador

Mensaje por zup » Jue Dic 31, 2015 8:28 am

Revisando un poco...

- Primero: ¿Para qué manipulas el stack? Si has hecho un CLEAR por debajo de 49000, no deberías hacer nada de eso.
- Segundo: Te cargas tu mismo el espacio disponible. Al retornar, el espacio está en el registro hl, y al hacer push af/pop hl lo sobreescribes. El código correcto debería ser

Código: Seleccionar todo

call dos_espacio
ld (dosret),hl
push af
pop hl
- Tercero: Control de errores. No hay, y no informas al BASIC si los ha habido. Mi variante sería algo así (resumida):

Código: Seleccionar todo

(pon rom3/ram7)
  ld a,65
  call dos_espacio
  jnc no_error     ; si no hay error, devolveremos el número de K libres
  ld hl, 65535     ; si hay error retornamos 65535
no error:
  push hl     ; guardamos en la pila lo que vamos a devolver
(pon rom2/ram0)
  pop bc     ; recuperamos en BC el valor de la pila para retornar al BASIC
  ret
- Cuarto: En la segunda paginación no habilitas las interrupciones al terminar. No es problema al retornar al BASIC, pero tenlo en cuenta.

- Quinto: Asumes que vuelves a una configuración BASIC estándar (ROM2/RAM520). Eso está bien si no utilizas paginación en tu programa BASIC, pero no tendría por qué ser así. Si tienes duda de si vas a utilizar la RAM extra o no, mejor preserva antes el valor de bankm y restáuralo al final.

A ver qué tal te sale la cosa...
I have traveled across the universe and through the years to find Her. Sometimes going all the way is just a start...

K.O.D.
Jack The Nipper
Mensajes: 115
Registrado: Mar Sep 30, 2008 8:45 am
Ubicación: Valencia

Re: Duda ensamblador

Mensaje por K.O.D. » Jue Dic 31, 2015 2:23 pm

zup escribió:A ver qué tal te sale la cosa...
Gracias por la respuesta. Ya te digo que yo de CM, cortito. Localicé aquí (http://www.users.globalnet.co.uk/~jg27p ... ntents.htm) un programa interesante (+3 BASIC DOS Demo) que hace llamadas desde BASIC a varias rutinas (DOS_VERSION, etc), ahora estaba destripándolo a ver qué descubría.

Un saludo y gracias otra vez.

(Y feliz Año Nuevo : )

zup
Freddy Hardest
Mensajes: 666
Registrado: Vie Ago 15, 2008 2:43 pm

Re: Duda ensamblador

Mensaje por zup » Jue Dic 31, 2015 3:54 pm

No uso pasmo, como escribo trozos cortos de ensamblador uso el ensamblador integrado de ZX Spin. Imagino que esto funcionará haciendo unos pocos cambios.

Este código lo he mirado y funciona perfectamente:

Código: Seleccionar todo

dos_open	equ 262
dos_close	equ 265
dos_abandon	equ 268
dos_read	equ 274
dos_write	equ 277
dos_set1346	equ 319
dos_free_space	equ 289
dos_set_pos	equ 310
dd_l_off_motor	equ 412
BANK678		equ 23399
BANKM		equ 23388
; estas definiciones pueden usarse en otras rutinas

inicio		equ 40000

; inicio

org inicio
  ld a,(BANKM)		; cojo la configuración ROM/RAM actual
  ld (pagina_inicial),a	; y me la guardo por ahí

; paginar DOS
  ld a,$07
  call paginar		; poner ROM2/RAM7

; leer el espacio libre en A:
  ld a,'A'
  call dos_free_space
  jr c,sin_error	; si no hay error, devolveremos el número de K libres
  ld hl, 65535		; si hay error retornamos 65535
sin_error:
  push hl		; guardamos en la pila lo que vamos a devolver

  ld a,(pagina_inicial)	;recupero la configuración ROM/RAM antigua
  call paginar		; y la pongo

  pop bc		; recuperamos en BC el espacio libre
  ret

; rutina de paginación
; en a pones la configuración ROM/RAM a seleccionar
paginar:
  di
  ld bc,32765
  ld (BANKM),a
  out (c),a
  ei
  ret

; variables
pagina_inicial db 0
Lo he probado tanto en un +3 (usando A y M) y en un +3e (usando C). Si todo va bien, devuelve al BASIC el espacio libre; si algo va mal devuelve 65535. El espacio máximo libre serían 16384K (una partición +3e totalmente limpita), así que no importa devolver el error como 65535.

El listado BASIC que lo acompaña:

Código: Seleccionar todo

10 CLEAR 39999
20 LOAD "free.bin" CODE 40000
30 LET a=USR 40000
40 IF a=65535 THEN PRINT "Error!":STOP
50 PRINT a,;"K libres"
I have traveled across the universe and through the years to find Her. Sometimes going all the way is just a start...

Avatar de Usuario
Rafa
Jack The Nipper
Mensajes: 181
Registrado: Lun May 07, 2007 11:59 am

Re: Duda ensamblador

Mensaje por Rafa » Mar Ene 05, 2016 10:55 am

La función USR devuelve el valor del par de registros BC, no de HL.
RANDOMIZE USR 0

Avatar de Usuario
Rafa
Jack The Nipper
Mensajes: 181
Registrado: Lun May 07, 2007 11:59 am

Re: Duda ensamblador

Mensaje por Rafa » Mar Ene 05, 2016 10:57 am

Ah ok, estaba bien.
RANDOMIZE USR 0

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 16 invitados