Получение терминальных столбцов и строк в сборке x86_64 - PullRequest
0 голосов
/ 25 ноября 2018

Как видно из заголовка, есть ли способ получить столбцы и строки, как в сборке x86_64?

РЕДАКТИРОВАТЬ: я забыл упомянуть, я очень плохо знаком с сборкой x86_64 (я начал вчера вечером).

1 Ответ

0 голосов
/ 25 ноября 2018

Вы можете получить размер терминала с помощью системного вызова .16 (sys_ioctl) .Его параметры идентичны функции C ioctl.Соответствующая команда: TIOCGWINSZ.

Давайте получим некоторую информацию с C:

// inspired by https://linux.die.net/man/4/tty_ioctl

#include <unistd.h>
#include <sys/ioctl.h>
#include <stdio.h>

int main (void)
{
    struct winsize sz;

    printf("STDOUT_FILENO = %u\n", STDOUT_FILENO);
    printf("TIOCGWINSZ = 0x%X\n", TIOCGWINSZ);
    printf("SIZEOF sz (bytes): %lu\n", sizeof sz);

    ioctl(STDOUT_FILENO, TIOCGWINSZ, &sz);

    printf("Screen width: %u  Screen height: %u\n", sz.ws_col, sz.ws_row);
    return 0;
}

Вызов sys_ioctl с NASM:

; Name:     get_terminal_size.asm
; Assemble: nasm -felf64 get_terminal_size.asm
; Link:     ld -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -o get_terminal_size get_terminal_size.o
; Run:      ./get_terminal_size

section .data
    fmt db `Screen width: %u  Screen height: %u\n`,0                ; backticks for '\n'

section .bss
    sz RESW 4

section .text
global _start
extern printf, exit

_start:

; http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
; https://linux.die.net/man/4/tty_ioctl

    mov eax, 16                 ; Kernel function SYS_IOCTL
    mov edi, 1                  ; STDOUT
    mov esi, 0x5413             ; TIOCGWINSZ
    mov edx, sz                 ; struct winsize sz
    syscall                     ; Call Linux

    mov rdi, fmt                ; string pointer
    movzx esi, WORD [sz+2]      ; sz.ws_col
    movzx edx, WORD [sz+0]      ; sz.ws_row
    xor eax, eax                ; no vector registers used
    call printf                 ; Call libc

    xor edi, edi                ; Exitcode 0 = exit(0)
    call exit                   ; Call libc

Стиль AT & T:

# Name:     get_terminal_size.s
# Compile:  gcc -m64 -oget_terminal_size get_terminal_size.s
# Run:      ./get_terminal_size

.section .data
fmt:    .asciz "Screen width: %u  Screen height: %u\n"

.section .bss
.lcomm  sz, 8

.section .text
.globl main
main:

# http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
# https://linux.die.net/man/4/tty_ioctl

    mov $16, %eax           # Kernel function SYS_IOCTL
    mov $1, %edi            # STDOUT
    mov $0x5413, %esi       # TIOCGWINSZ
    mov $sz, %edx           # struct winsize sz
    syscall                 # Call Linux

    mov $fmt, %rdi          # string pointer
    movswl (sz+2), %esi     # sz.ws_col
    movswl (sz+0), %edx     # sz.ws_row
    xor %eax, %eax          # no vector registers used
    call printf             # Call libc

    xor %edi, %edi          # Exitcode 0 = exit(0)
    call exit               # Call libc
...