NASM Forum > Programming with NASM

Problems using div?

(1/3) > >>

Luns:
Sorry if this isn't specifically NASM-related, but I'm not sure of another board where I could ask this - how exactly do syscalls work?  For example, if I'm using Linux and call sys_write (with int 0x80 and 4 in eax), what happens to print out a message?  I know the syscall is defined in read_write.c in the Linux source, and if you go there then it seems to call do_sendfile (), which then calls fput_light (), which then calls fput () and then __fput ()... I lost it a few functions after that.  At the root of it all, is there something calling a BIOS interrupt to print out the message?  Is there any assembly along the way or is it all implemented in C?

Thanks, just trying to wrap my head around this...

e:  New question below.
e2: Another new question!

Frank Kotler:
You've done well to track it down that far! We do have the source code. Given the skill and persistance, we should be able to figure out exactly how it all works. I find it heavy going! I suspect that if you spend enough time with kernel code, and get "oriented", it gets easier. I'm not there yet, and I'm not working too hard at it...

For general "syscalls" processing, this seems to be relevant:

/usr/src/linux/arch/i386/kernel/entry.S

I see, in /usr/src/linux/arch/i386/boot/video.S, we do use BIOS int 10h calls (and some "outw"s to ports, as well). If I were writing an OS, I've often thought, I wouldn't be in any hurry to switch to pmode, but would interrogate the BIOS mercilessly while still in rmode, and save what I found. Maybe even switch to a video mode, while BIOS was still available. It looks to me like this file is doing something like that(?).

It would be possible to use BIOS ints after switching to pmode, using the vm86 sys_call, but I doubt (guessing) that it is used here. I suspect that if sys_write is to STDOUT, and if STDOUT is not redirected - we're really printing to the screen - that we write to 0xB8000 (or possibly 0xA0000 if we're not in "text mode" - say a "linear frame buffer" has been specified), or probably a second buffer (per process) which gets copied to 0xB8000 when it's "our turn"... I haven't found the exact code that does this - I suspect it's done in C, not asm - but I'm guessing that's what happens.

As to where else you might ask these questions, the kernel developers' list probably doesn't welcome such "newbie questions". I'd poke around here:

http://kernelnewbies.org/

I suspect they aren't much into assembly language. There's a "linux-assembly" list that might be helpful. Subscribe by sending:

subscribe linux-assembly

in the message body to:

majordomo@vger.kernel.org

Of course, if you're molesting these sys_calls using Nasm, it's on topic here. :)

Best,
Frank

Luns:
Ah, that all makes a lot of sense.  Thanks, that's cleared up some stuff for me.

Luns:
Sorry to bump this up, but I thought it would be better just to post again here rather than make another topic...

Now I have an array of characters, which I'd like to print (through stdout) with a Linux syscall.  I can loop through the array and get each value fine, but my problem is the syscall wants a pointer to the value be in ecx, not the value itself.  Is it possible to put a pointer to a specific array value into a register?

Bryant Keller:
If you have an array of characters, it would be easier (and better all around) to just print the whole string.


--- Code: ---BITS 32
CPU 486

SECTION .data

strHey: DB "Hello, World!", 10
strHey_size EQU ($-strHey)

SECTION .text

GLOBAL _start
_start:
        mov edx, strHey_size ; strlen = sizeof("Hello, World!")
        mov ecx, strHey ; pstr = address of strHey
        mov ebx, 1 ; fileno = STDOUT
        mov eax, 4 ; SYS_write
        int 0x80

        mov ebx, 0 ; errcode = 0
        mov eax, 1 ; SYS_exit
        int 0x80
--- End code ---

However, if you have your heart set on doing it one character at a time, you could try something like.


--- Code: ---BITS 32
CPU 486

SECTION .data

strHey: DB "Hello, World!",10
strHey_size EQU ($-strHey)

SECTION .text

GLOBAL _start
_start:
        mov esi, strHey ;; address of array
        lea edi, [strHey + strHey_size] ;; address of end of array
.nextchar:
        pushad

        mov edx, 1 ; strlen = 1
        mov ecx, esi ; pstr = address_of(strHey[index])
        mov ebx, 1 ; fileno = STDOUT
        mov eax, 4 ; SYS_write
        int 0x80

        popad
        inc esi ;; move to next character
        cmp esi, edi ;; are we at the end of the array
        jne .nextchar

        mov ebx, 0 ; errcode = 0
        mov eax, 1 ; SYS_exit
        int 0x80
--- End code ---

This is, of course, untested code. Unfortunately with me, untested code can (and very often does) fail, so good luck building it. the idea is there though, just increment through until you reach the end and use SYS_write with a length value of 1.

[EDIT: Keith tested it for me. it's good]

Navigation

[0] Message Index

[#] Next page

Go to full version