+ Reply to Thread
Results 1 to 6 of 6

Thread: Intro to Intel Assembly Language: Part 7

  1. #1
    Join Date
    Oct 2007
    Location
    /dev/null
    Posts
    4,513
    Blog Entries
    8
    Rep Power
    59

    Intro to Intel Assembly Language: Part 7

    Welcome back to Intro to Intel Assembly Language. If you haven't read them already, I suggest taking a look at the previous tutorials so you don't get lost.

    Today we're going to cover software interrupts and system calls, if I have space. Using our knowledge from previous tutorials, we're going to create a printint function and a readint function that, well, do exactly what they say.

    Software Interrupts
    A long long time ago, in a PC far far away, there was this thing called a BIOS--Basic I/O System. It had two main functions:
    1) Load the operating system*
    2) Provide a library of functions for programs to use to perform tasks such as drawing on the screen, reading from the keyboard, read and write from files, and so on.

    * Actually the BIOS would load a bootstrap loader provided by the operating system in a fixed location on the disk. Because the loader could only be 460 bytes long at most, cramming the entire operating system in there was impractical. So the loader was jammed in there, and it found the operating system on the disk and loaded that.

    The BIOS was slow because it was designed to work with just about any hardware, but it was convenient for programmers to use. Eventually faster and more secure device drivers were developed, and calls were made to the operating system, not the BIOS. The operating system then used the device drivers to talk to the hardware. For simplicity we're going to use the BIOS because it's the same across all operating systems. After you're comfortable with that, then I'll get into using system calls (the modern way). There'll be a section on Linux and Windows, so no one really gets left out. (Mac people, go with the Linux part as Macs are based on Unix anyway.)

    I must warn you, though, that I cannot guarantee these programs will work on Linux without DOSEMU. The reason is that Linux doesn't let you execute pure binary code, but Windows does provided that it's 64KB or less, subject to a few restrictions on port I/O and other potentially dangerous functions. Linux under DOSEMU works just like Windows in this respect. You cannot use interrupts in modern 32- or 64-bit programs, as the operating system will block them and crash your program for security reasons. Besides, device drivers are faster and provide better control than the BIOS. Really the only time you'd need the BIOS is if you're writing a bootstrap loader or something that cannot run on top of an operating system.

    Interrupts
    The BIOS library is divided into a bunch of sections called interrupts. Each interrupt handled a different aspect of the computer--keyboard I/O, screen drawing functions, file and disk I/O, and so on. Each interrupt then had a whole bunch of functions, each given a number. They used AH (and if the interrupt had a lot of functions, AX) to determine which function to call. Arguments to the interrupts were passed in registers instead of on the stack to speed things up a bit. Let's look at a simple interrupt call:

    INTERRUPT 21H, SUBFUNCTION 3DH: Open File
    Arguments
    AH - 3Dh
    AL - Access and sharing modes (0:read, 1:write, 2:read/write, etc.)
    DS:DX - Null-terminated string containing path to file. Must be in 8.3 format.

    Return Values
    Carry flag clear on sucess, set on error
    AX - file handle if CF=0, error code if CF=1

    Unless stated, you can safely assume that all registers not listed in the "return values" section are untouched. This is because interrupt calls automatically save all registers (except the stack pointer) before they jump to the interrupt function.

    You can get information on every function of every interrupt here.

    We're going to concern ourselves with two functions of interrupt 21H: 09H--print string to console, and 0AH--read string from keyboard. If we look at our handy reference, we see:

    INT 21H, SUBFUNCTION 09H: Write string to standard output
    Arguments
    AH - 09H
    DS:DX - String terminated by '$'

    Return Values
    AL is trashed.

    ----------------

    INT 21H, SUBFUNCTION 0AH: Buffered Input
    Arguments
    AH - 0AH
    DS:DX - Buffer
    The first byte of the buffer indicates the buffer size. This means that a maximum of 255 bytes may be read.
    Upon returning, second byte of the buffer contains the number of characters actually read from STDIN, including the carriage return.
    In short, if you want to read X bytes, your buffer needs to be X + 2 bytes long.

    Return Values
    Buffer filled with user input, second byte contains number of bytes read.

    Let's get to it! To create our readint and writeint functions, we first need functions to convert a string to an integer, and an integer to a string. Because I'm lazy and these have little to do with what I'm trying to teach, I'm just going to assume that we have two functions called int2string and string2int with the following prototypes:

    Code:
    /*returns length of string written*/
    uint8_t int2string(uint32_t integer, char *buffer);
    
    /*returns int value of string representation*/
    uint32_t string2int(const char *str);
    Let's try making writeint since I think it's easier:
    Code:
    _writeint:
        push    ebp
        mov     ebp, esp
        
        ;create 14-byte buffer for our
        ;integer, since the maximum number
        ;is 4294967295 (13 chars) plus our
        ;terminating '$'
        sub     esp, 0eh
        
        ;get our 32-bit integer to print
        mov     eax, [ebp + 8]
        
        push    esp     ;buffer address
        push    eax     ;integer to convert
        call    _int2string
        
        ;AL now contains the number of bytes
        ;written to our buffer. however, the
        ;upper 24 bits of EAX contain garbage.
        ;we need to clear them, so we'll use
        ;AND with a mask to zero them out.
        and     eax, 000000ffh
        
        ;terminate our string with '$'
        mov     [esp + eax], '$'
        
        ;print our string to STDOUT. because
        ;our buffer is in the stack segment,
        ;we need to make sure that DS=SS.
        ;
        ;save DS and then set DS = SS
        push    ds
        push    ss
        pop     ds
        
        ;DS:EDX must point to our buffer
        mov     edx, esp
        mov     ah,09h
        int     21h
        
        ;restore DS to original value
        pop     ds
        
        ;clean up stack and return
        add     esp, 0eh
        pop     ebp
        ret
    Not too bad, now is it? readint takes a little more work:
    Code:
    _readint:
        push    ebp
        mov     ebp, esp
        
        ;create buffer for STDIN input
        sub     esp, 101h
        
        ;set buffer length for BIOS routine
        mov     [esp], 0ffh
        
        ;same as before
        push    ds
        push    ss
        pop     ds
        
        mov     edx, esp
        
        ;call read routine
        mov     ah, 0ah
        int     21h
        
        ;replace terminating CR with null
        mov     al, [esp + 1]
        and     eax, 000000ffh
        mov     [esp + eax + 1], 00h
        
        ;convert to int, skip over buffer
        length and bytes read counts
        lea     eax, [esp+2]
        push    eax
        call    _string2int
        
        ;clean up and return
        pop     ds
        add     esp, 101h
        pop     ebp
        ret
    I hope you've enjoyed this introduction to BIOS routines. Next time I'll teach you a few more useful interrupts that you might use for coding a bootloader, and then get on to system calls.

    Next In This Series
    Intro to Intel Assembly Language: Part 8
    Last edited by dargueta; 11-18-2010 at 07:23 PM.
    sudo rm -rf /

  2. CODECALL Circuit advertisement
    Join Date
    Always
    Location
    Advertising world
    Posts
    Many

     
  3. #2
    Join Date
    Jul 2006
    Posts
    16,491
    Blog Entries
    75
    Rep Power
    143

    Re: Intro to Intel Assembly Language: Part 7

    Very nice! BIOS calls can also work around some OS imposed restrictions, I would imagine. +rep
    Programming is a branch of mathematics.
    My CodeCall Blog | My Personal Blog

  4. #3
    Join Date
    Oct 2007
    Location
    /dev/null
    Posts
    4,513
    Blog Entries
    8
    Rep Power
    59

    Re: Intro to Intel Assembly Language: Part 7

    BIOS calls can also work around some OS imposed restrictions, I would imagine.
    No. There is a BIOS interrupt function that allows you to redirect BIOS interrupts to your own code. Operating systems use this to patch in code that performs security checks first. If the requested interrupt is safe to execute, or the calling program has the correct privileges, then the operating system calls the actual BIOS code and returns. Otherwise, the OS blocks the interrupt and takes appropriate action (usually causing an access violation and crashing the program).

    EDIT: Slight clarification: Most modern OS's switch into protected mode on startup. Not even the OS can access interrupts in this mode. However, if the operating system finds it has to run a program in 16-bit compatibility mode, it switches to VM86 mode (Virtual Monitored 8086) where the program thinks it's running in 16-bit real mode. Whenever a software interrupt is called, the processor automatically switches over to protected mode and the OS handles the interrupt. It can then switch back to VM86 mode and continue deceiving the program.

    A little more info on the different modes of the x86 processor:
    Real Mode (The old 8086 - all x86 processors boot in this mode.)
    VM86 Mode (Faked real mode)
    "Unreal" Mode (Basically real mode tweaked to have more memory)
    Protected Mode (The mode most operating systems use to protect programs from overwriting each other)
    System Management Mode (Special firmware executes stuff like emergency shutdowns when the CPU gets too hot, etc.)
    Long mode (An AMD thing that I don't understand.)
    Last edited by dargueta; 03-19-2010 at 01:26 AM. Reason: Clarification
    sudo rm -rf /

  5. #4
    Join Date
    Jul 2006
    Posts
    16,491
    Blog Entries
    75
    Rep Power
    143

    Re: Intro to Intel Assembly Language: Part 7

    What I'm thinking of is things like CD-ROM copying that tries to "interpret" the data rather than just copy it. Of course, I could be completely wrong.
    Programming is a branch of mathematics.
    My CodeCall Blog | My Personal Blog

  6. #5
    Join Date
    Oct 2007
    Location
    /dev/null
    Posts
    4,513
    Blog Entries
    8
    Rep Power
    59

    Re: Intro to Intel Assembly Language: Part 7

    You could do the same with read() from /dev/cdrom0 on Linux or ReadFile on \\.\D: (whatever the CDROM drive is) on Windows. It'd probably be faster than using the BIOS, plus you're not stuck using 16-bit pointers and buffer sizes.
    Last edited by dargueta; 12-28-2009 at 11:08 AM. Reason: Grammar
    sudo rm -rf /

  7. #6
    g-man122 is offline Newbie
    Join Date
    Dec 2009
    Location
    Where do you live ?
    Posts
    29
    Rep Power
    0

    Re: Intro to Intel Assembly Language: Part 7

    Great job on all 7 tutorials - great explanation, great examples and fantastic way of teaching. I hope to see more. +rep!

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Intro to Intel Assembly Language: Part 9B
    By dargueta in forum Assembly Tutorials
    Replies: 7
    Last Post: 10-02-2010, 10:08 PM
  2. Intro to Intel Assembly Language: Part 9A
    By dargueta in forum Assembly Tutorials
    Replies: 4
    Last Post: 08-16-2010, 09:06 AM
  3. Intro to Intel Assembly Language: Part 8
    By dargueta in forum Assembly Tutorials
    Replies: 6
    Last Post: 07-15-2010, 09:21 AM
  4. Intro to Intel Assembly Language: Part 5
    By dargueta in forum Assembly Tutorials
    Replies: 6
    Last Post: 03-07-2010, 12:45 PM
  5. Intro to Intel Assembly Language: Part 6
    By dargueta in forum Assembly Tutorials
    Replies: 3
    Last Post: 12-14-2009, 06:06 PM

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts