davidgiven / ack

The Amsterdam Compiler Kit
http://tack.sf.net
Other
420 stars 59 forks source link

[question] Inline Assembly possible for the msdos86 an pc86 Targets? How? #233

Closed Fabrizio-Caruso closed 3 years ago

Fabrizio-Caruso commented 3 years ago

I would like to implement non-waiting keyboard input and some simple vga output on the msdos86 and pc86 targets.

I am grepping the repo searching for "asm" but I have not found any example.

How can I use Assembly with C? Which syntax can I use?

I need to do simple things such as:

mov ax, 0013h
int 10h
davidgiven commented 3 years ago

It does have inline assembly --- the em architecture doesn't allow it. Instead you have to create .s assembly files, assemble them to .o files, and link them. The ack front-end knows about assembly files so you can just add them to your source file list. The assembler syntax is kinda weird, though. See https://github.com/davidgiven/ack/blob/default/plat/pc86/libsys/_sys_rawread.s for an example. Note that you must have that section declaration clause at the top, or it won't work.

Fabrizio-Caruso commented 3 years ago

I have tried something the following code below. I see a black screen on dosbox which may be a good sign for the Assembly part but I am not sure I am able to write into the screen memory:

#define POKE(addr,val)     (*(unsigned char*) (addr) = (val))
#define POKEW(addr,val)    (*(unsigned int*) (addr) = (val))
#define SCREEN_BASE 0xA0000000
#include <stdlib.h>
extern void init_vga(void);
void _XL_INIT_GRAPHICS(void) {
    uint16_t i;
    init_vga();
    for(i=0;i<1000;++i) {
        POKEW(SCREEN_BASE+i,0xFFFF);  
    }
    while(1){};
}

which I link with init_vga.s:

.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .text
.define _init_vga
_init_vga:
    mov ax, 0x0013
    int 0x10
    ret
davidgiven commented 3 years ago

You haven't set the segment when writing --- you'll have to move POKEW into another assembly function and write it via mov [es:dx], ax or something similar. (Remember the ack makes small mode binaries. Pointers are 16 bits.)

Fabrizio-Caruso commented 3 years ago

@davidgiven can't I just do it with the C macro POKEW that uses C pointers to write into memory?

#define POKEW(addr,val) (*(unsigned int*) (addr) = (val)) or maybe #define POKEW(addr,val) (*(unsigned uint16_t*) (addr) = (val))

davidgiven commented 3 years ago

No, that just does a normal write to the 64kB data segment --- mov [ds:dx], ax. Video memory's somewhere else entirely. Segmented architectures are fun.

Fabrizio-Caruso commented 3 years ago

Thanks @davidgiven! So I need to implement an Assembly version of the POKEW, which takes arguments. Do I need to do this in a different file? I don't understand the purpose of the segment declarations. Do I need a special one for POKEW?

davidgiven commented 3 years ago

You can put it in the same file. The final .text segment declaration just tells the assembler that this is code. (The initial ones make sure the segments are numbered correctly.)

The ACK passes all parameters on the stack, which is irritating. Look at https://github.com/davidgiven/ack/blob/default/plat/pc86/libsys/_sys_rawwrite.s for this.

Fabrizio-Caruso commented 3 years ago

So, there is no syntax for arguments? I will need to have a C function that writes into screen ram: some sort of POKEW(uint16_t address, uint16_t value). So I have two 16-bit arguments. How can I do this? Are arguments somehow mapped to 16-bit words on the stack? Like the first 16-bit word popped from the stack is the first argument and the second 16-bit word is the second parameter?

davidgiven commented 3 years ago

They're pushed onto the stack from left-to-right, and will appear above the return address. So, the last parameter is at 2(sp), the second last at 4(sp), etc. Once you've pushed the old bp they'll be at 4(bp) and 6(bp). You can see the routine I linked to above accessing a parameter at 4(bp).

Fabrizio-Caruso commented 3 years ago

Thanks! I am getting some help on how to write the routine. I don't know, yet, if I will manage. I would close this issue for the moment. I might come back with more questions if I am stuck, again.

tkchia commented 2 years ago

Hello @Fabrizio-Caruso,

In case you are (still) interested in this issue:

My libi86 library, which supports ACK's msdos86 target, currently includes implementations of peek, peekb, poke, and pokeb functions for working with far addresses.

You can consider either using this through the library (in _BORLANDC_SOURCE mode). Alternatively, you might want to study the source code to see how to implement similar functionality in your own program.

Thank you!