RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / user-385192

nx4n's questions

Martin Hope
nx4n
Asked: 2024-03-15 01:55:17 +0000 UTC

为什么我们需要 .org 0x7C00 指令来从头开始运行代码?从磁盘的第一个扇区运行代码

  • 8

许多消息来源写道,有必要在汇编代码中插入一个指示地址的指令.org 0x7C00,据说代码从该地址开始执行(更准确地说,BIOS从磁盘的第一个扇区进入那里)。该指令存在于 Linux 内核源代码和许多其他源代码中,例如https://github.com/fffaraz/bootloader/blob/master/bootloader.asm(顺便说一句,nasm 立即生成一个文件512字节,也不清楚为什么,只有一个猜测:它被自动“trunked”。这个“顺便说一下”指的是链接后的文本)。

理论上说:需要设置16位模式,BIOS读取第一个扇区,分别检查511和512字节是否存在0x55和0xAA,如果检查成功,则将代码放置在地址处0x0000:0x7C00 并开始执行。

我只是想在启动时在屏幕上显示“X”,这是代码和后续步骤:

.org 0x7C00
.code16
start:
    mov $'X', %al
    mov $0xE, %ah
    int $0x10
    cli
    hlt
    . = start + 510
    .byte = 0x55
    .byte = 0xAA

我编译:

as -o boot.o boot.S

我得到 objdump -D

boot.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <_start-0x7c00>:
    ...

0000000000007c00 <_start>:
    7c00:   b0 58                   mov    $0x58,%al
    7c02:   b4 0e                   mov    $0xe,%ah
    7c04:   cd 10                   int    $0x10
    7c06:   fa                      cli
    7c07:   f4                      hlt
    ...
    7dfc:   00 00                   add    %al,(%rax)
    7dfe:   55                      push   %rbp
    7dff:   aa                      stos   %al,%es:(%rdi)

Disassembly of section .note.gnu.property:

0000000000000000 <.note.gnu.property>:
   0:   04 00                   add    $0x0,%al
   2:   00 00                   add    %al,(%rax)
   4:   20 00                   and    %al,(%rax)
   6:   00 00                   add    %al,(%rax)
   8:   05 00 00 00 47          add    $0x47000000,%eax
   d:   4e 55                   rex.WRX push %rbp
   f:   00 02                   add    %al,(%rdx)
  11:   00 01                   add    %al,(%rcx)
  13:   c0 04 00 00             rolb   $0x0,(%rax,%rax,1)
    ...
  1f:   00 01                   add    %al,(%rcx)
  21:   00 01                   add    %al,(%rcx)
  23:   c0 04 00 00             rolb   $0x0,(%rax,%rax,1)
  27:   00 01                   add    %al,(%rcx)
  29:   00 00                   add    %al,(%rax)
  2b:   00 00                   add    %al,(%rax)
  2d:   00 00                   add    %al,(%rax)

我删除 .note.gnu.property

strip --remove-section=.note.gnu.property boot.o

关联:

ld --oformat binary -o boot boot.o

输出是一个大小为 32256 字节的文件。呵呵,当然,代码是从0x7C00开始的!查看该文件的十六进制转储,您可以看到该“地址”之前有零。那么问题来了,人们如何将这个文件写入第一个 512 字节扇区呢?当然没办法,有人不告诉什么,qemu-system-i386 -drive format=raw,file=boot他们甚至不会运行这个文件,前512字节中不会有代码

如果我们删除.org 0x7C00,生成的文件大小将恰好为 512 字节。这个文件已经可以启动qemu了。

如何在计算机启动时将控制权从 USB 转移到代码。我这样做:

为此,我使用 dd 实用程序。团队:

dd if=boot of=/dev/sdb bs=512 count=1 conv=notrunc

一切都被记录下来,hexdump也适用于/dev/sdb,前512的内容是相同的。qemu可以运行/dev/sdb

在BIOS中,我禁用安全模式,启用CSM支持(毕竟,uefi已经无处不在),准备好,转到启动选项卡,BIOS看到这个闪存驱动器(顺便说一下,KingstonDatatraveler 3.0),选择它,启动它,打印出令人垂涎的“X”符号。该代码无需 .org 0x7C00 即可运行。

问题:为什么需要这个指令?

更新:

现在我将0xAA更改为0xAF,代码仍然可以读取并运行。我是这样理解的:BIOS(没有uefi)仅将第一个扇区的前440字节复制到RAM中(https://wiki.archlinux.org/title/Arch_boot_process),这意味着它不会读取后续扇区和0x55和 0xAA 并不重要,它们是 uefi 所需要的。

问:我理解的对吗,或者是怎么回事?

ассемблер
  • 1 个回答
  • 50 Views
Martin Hope
nx4n
Asked: 2022-12-01 17:48:30 +0000 UTC

切换当前进程组

  • 6

有代码调用一个fork,将当前终端组切换到一个新的组,这个组的leader是fork之后的进程,之后的主进程只是等待child完成。

新进程执行某些操作后,当前终端组切换到之前的终端组,但如果新进程因信号而终止怎么办?它没有到达将组切换到上一个组的代码行,结果发现主进程现在已保留在后台。

我为此使用 tcsetpgrp。

问题更简单:如何在没有活动进程参与的情况下使后台进程成为当前进程(例如,如果活动进程已经结束)。

更新(代码):

int main(int argc, char **argv)
{
        int32_t pid;
        pid = fork();
        if (pid == -1) {
                perror("fork");
                exit(1);
        }
        if (pid == 0) {
                execlp("cat", "cat", NULL);
                perror("cat");
                fflush(stderr);
                _exit(EXIT_FAILURE);
        }
        setpgid(pid, pid);
        tcsetpgrp(0, pid);
        wait(NULL);
        tcsetpgrp(0, getpgid(getpid())); // не работает?
        int32_t c = 0;
        while ((c = fgetc(stdin)) != 'g');
        return 0;
}

运行代码的一个例子,就是“cat”启动,进入asd,程序也发出asd,我按ctrl+c,“cat”结束就这样,主进程还是后台。

例子

linux
  • 2 个回答
  • 59 Views
Martin Hope
nx4n
Asked: 2022-09-29 12:21:27 +0000 UTC

如何限制字符数组传递给函数

  • 0

有常数:

const uint8_t background_part[5] = "\" & \"";
const uint8_t and_part[6] = "\" && \"";
const uint8_t output_to_start_part[5] = "\" > \"";
const uint8_t output_to_end_part[6] = "\" >> \"";
const uint8_t input_from_part[5] = "\" < \"";
const uint8_t bracket_left_part[5] = "\" ( \"";
const uint8_t bracket_right_part[5] = "\" ) \"";

另一个模块中有一个函数:

int32_t comp_last_copa_part (const copa *t, const uint8_t *buf, int32_t ssize_buf);

当您将 background_part 常量作为 buf 参数传递给它时,例如,在 gdb 调试器中,会发生以下情况:

comp_last_copa_part (t=0x55555555b2e0, buf=0x555555557093 <background_part> "\" & \"\" && \"\" > \"\" >> \"\" < \"\" ( \"\" ) \"Set termios new attributes", size_buf=5)

问题:为什么要传递这样一个字符串?什么是 buf=0x555555557093 <background_part> "" & "" && "" > "" >> "" < "" ( "" ) "设置 termios 新属性"

“Set termios”通常是 perror 中的一行,这是一个代码片段,它位于常量声明的下方:

} else {
        perror("Set termios new attributes");
        exit(1);
}

这个问题我不知道怎么命名,如果版主知道,请指正。

当然,我从代码中可以看出为什么会这样,比如这是下面所有行的开头,但是在我看来这是不正确的,这样的问题是如何解决的呢?

c gdb
  • 1 个回答
  • 42 Views
Martin Hope
nx4n
Asked: 2022-07-10 15:09:29 +0000 UTC

C、strstr的类比和字符串中子串的出现次数

  • -1

该程序将 1 个参数作为子字符串,然后是字符串。如果后续行中有子字符串,则需要显示此行以及其中子字符串的出现次数:

#include <stdio.h>

char *sub_string(const char *str, const char *s_str); /*str - строка, s_str - подстрока*/

int main(int argc, char **argv)
{
        int i, count, ssl;
        char *str;
        argv++;
        if(argc < 2){
                fprintf(stderr, "Incorrect args\n");
                return 1;
        }
        for(ssl = 0; (*argv)[ssl]; ssl++); /*ssl = (длина подстроки с '\0' символом) - 1*/
        puts("Args with substring:");
        for(i = 1; argv[i]; i++){
                count = 0;
                str = argv[i];
                while(sub_string(str, *argv)){
                        count++;
                        str += ssl;
                }
                if(count > 0)
                        printf("%s, substring's count: %d\n", argv[i], count);
        }
        return 0;
}

char *sub_string(const char *str, const char *s_str)
{
        char *str_ptr, *s_str_ptr;
        int trigger;
        while(*str){
                if(*str == *s_str){
                        trigger = 1;
                        str_ptr = str;
                        s_str_ptr = s_str;
                        while(*str_ptr && *s_str_ptr){
                                trigger &= (*str_ptr == *s_str_ptr);
                                str_ptr++;
                                s_str_ptr++;
                        }
                        if(trigger && !(*str_ptr) && *s_str_ptr)
                                return NULL;
                        if(trigger)
                                return str;
                }
                str++;
        }
        return NULL;
}

问题:

当我使用以下参数调用程序时:./prog "asd" "1asd2asd3asd"它给了我1asd2asd3asd, substring's count: 4. 为什么???

如果在一个循环中

                    while(sub_string(str, *argv)){
                            printf("%s\n", sub_string(str, *argv));
                            count++;
                            str += ssl;
                    }

добавить printf("%s\n", sub_string(str, *argv));

那么输出将是:

asd2asd3asdd
asd3asdd
asdd
asdd

为什么有asdd两次???3 次迭代后,d 应该保留并且函数应该返回 NULL,但它似乎又需要 asdd ...

当我打电话时,./prog "asd" "1asd2asdd"它给了我1asd2asdd, substring's count: 2。怎么了?我不明白前面的(和类似的例子)的例子有什么问题......这里Printf循环中的同一个例子会给出

asd2asdd
asdd

也就是说,一切都是应有的。我已经累了,胡说八道)))

c
  • 1 个回答
  • 52 Views
Martin Hope
nx4n
Asked: 2020-06-07 20:48:17 +0000 UTC

object.assign javascript

  • 2

:) 在这里我创建了 3 个对象:

let user = { who: "God", age: 13759613215 };
let obj1 = { someKey1: "dsvygsd" };
let obj2 = { someKey2: "sdvtglmha" };

复制属性 obj1 和 obj2 以及用户。

Object.assign( user, obj1, obj2 );

我通过警报调用键。

for (let key in user) {
    alert(key);
}

好吧,弹出窗口按顺序显示它们:谁,年龄,someKey1,someKey2。

所以我把方括号放在这里

Object.assign( user, [obj1, obj2] );

现在循环

for (let key in user) {
        alert(key);
    }

给我:0、1、谁、年龄。为什么有 0 和 1?

javascript
  • 3 个回答
  • 10 Views

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5