The lowest level function to handle a user input

冷暖自知 提交于 2019-12-24 21:40:19

问题


The following code I have reads the input from user similar to gets function in C language.

section .text
global _start

_start:
    mov eax, 3          ; Read user input into str
    mov ebx, 0          ; |
    mov ecx, str        ; | <- destination
    mov edx, 100        ; | <- length
    int 80h             ; \

    mov eax, 1          ; Return
    mov ebx, 0          ; | <- return code
    int 80h             ; \

section .data
    str: times 100 db 0 ; Allocate buffer of 100 bytes

I am not sure how Linux is handling my code, but I am curious how this code is handled on an Intel machine natively (without any OS). As far as I know, interrupt 80h is searched through an interrupt vector table and the related code function is called. But, going one step lower, how is that code written? I want to know how is the algorithm that handles such a functionality?

Can anyone please advise how to find the complete function code for handling user input with the lowest level on an actual machine? I am interested in both knowing the function and also finding the way to obtain such a code.


回答1:


At the lowest level (bare metal), there is no "function" you "call" with an int xx instruction. int xx can only invoke other code running on the CPU, not make something special happen.

Talking to hardware involves running code that uses loads or stores to generate PCI / PCIe transactions, or in/out instructions to access I/O space. (Or at least some access to special physical addresses; on older computers it wasn't necessarily PCI, and a few MMIO addresses on modern CPUs don't actually go off-chip so PCI isn't really involved.)

As far as I know, interrupt 80h is searched through an interrupt vector table and the related code function is called. But, going one step lower, how is that code written?

Yes, the Linux kernel (written in C and assembly) sets up the IDT so user-space int 80h will enter the kernel at its int80 handler entry-point.

int 80h / eax=3 in user-space just dispatches to the sys_read function in the Linux kernel, which implements the POSIX read() function / system call. (See What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code? for a bit about the kernel side of that dispatching to the table of system calls).

Think of int 0x80 (or the more efficient sysenter and syscall instructions) as ways to make a function call across a privilege boundary. All the magic is (as you guessed) in the implementation of that function inside the kernel, and the other functions it calls. (And the whole Unix model of "everything is a file"; this is the same system call you'd use to read a disk file.)

It takes a file-descriptor arg, in your case stdin = 0. That's just a file, often a TTY or pseudo-tty connected to a terminal emulator, which talks to an X11 server to get keyboard events. You could be running on a Linux text console (ctrl+alt+f2) in which case the kernel is running a terminal emulator with keyboard input coming from whatever physical keyboard(s) is/are connected. Or you could have redirected input from any type of file.

If I redirected input from /dev/input/by-id/usb-Logitech_USB_Receiver-if02-event-kbd on my system, I can get some raw keypress events but not in ASCII text format. (You can safely sudo cat that file; input still goes to your X server as well so you can control-C it). That's a more direct way to talk to the keyboard driver, but you're still going through Linux's HID (Human Interface Device) and event subsystem before you actually get to code that accesses the USB host controller connected to your keyboard.


There's nothing remotely similar you can do on bare metal; you'd use in / out or MMIO loads / stores to talk to a keyboard through a USB host control controller (e.g. eHCI or xHCI). https://wiki.osdev.org/Universal_Serial_Bus

(With BIOS emulation of a PS/2 keyboard, or on an old machine with a real PS/2 keyboard controller, you could talk to that much more easily. Back in early PC days, lots of different programs running in real mode would interact with hardware directly so there were simpler standards for how to access it, often with in and out instructions to well-known port numbers. No PCI bus enumeration or anything needed.

In modern PCs you can still do that, but mostly it's faked by software that traps the accesses. BIOS emulation is by definition not bare metal. Only motherboard firmware developers truly program bare metal. System Management Mode lets the firmware set up hooks that can run even after the OS boots. Fortunately most systems don't do much / any of that, although there are still ACPI tables that a kernel should read instead of probing hardware directly.)


If you boot a legacy bootloader, the firmware will switch back to real mode and set up a bunch of "BIOS services" which you can use via int 10h and other interrupt numbers. Much like running under a Linux kernel, you're not remotely close to talking "directly" to real hardware; all device-driver details are hidden behind a standard API. https://wiki.osdev.org/BIOS

If you boot a modern UEFI bootloader, again you have a standard API for accessing screen / keyboard, with "driver" code provided by the firmware. It's like a minimal kernel. https://wiki.osdev.org/UEFI


Once a real kernel like Linux boots, it does have device drivers for the real USB controllers. If the BIOS had set up emulation of PS/2 hardware, the kernel replaces / disables that.

Like I said, this Linux kernel code is written in C, with some inline asm wrappers for a few things.

  • https://github.com/torvalds/linux/tree/master/drivers/input/keyboard/ is a whole directory of keyboard drivers for various possible keyboard hardware. (I think separate from USB).
  • https://github.com/torvalds/linux/tree/master/drivers/usb/host/ drivers for USB host controllers. (Also other directories under drivers/usb/, like core/, have essential code)
  • https://github.com/torvalds/linux/blob/master/drivers/hid/usbhid/usbkbd.c Linux's USB keyboard driver. (There's a standard generic protocol for USB HID devices including keyboards; that's why most keyboards and mice can "just work" without needing special drivers even on Windows where the base OS doesn't have drivers for everything already built / available.)

This is almost certainly more code than you want to wade through, but it is the answer to your question.



来源:https://stackoverflow.com/questions/58569102/the-lowest-level-function-to-handle-a-user-input

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!