- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在学习使用C和内联汇编在DOS中进行一些低级VGA编程。现在,我正在尝试创建一个在屏幕上打印出字符的函数。
这是我的代码:
//This is the characters BITMAPS
uint8_t characters[464] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x50,
0x50,0x00,0x00,0x00,0x00,0x00,0x50,0xf8,0x50,0x50,0xf8,0x50,0x00,0x20,0xf8,0xa0,
0xf8,0x28,0xf8,0x00,0xc8,0xd0,0x20,0x20,0x58,0x98,0x00,0x40,0xa0,0x40,0xa8,0x90,
0x68,0x00,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x20,0x40,0x40,0x40,0x40,0x20,0x00,
0x20,0x10,0x10,0x10,0x10,0x20,0x00,0x50,0x20,0xf8,0x20,0x50,0x00,0x00,0x20,0x20,
0xf8,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x60,0x20,0x40,0x00,0x00,0x00,0xf8,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x08,0x10,0x20,0x40,0x80,
0x00,0x70,0x88,0x98,0xa8,0xc8,0x70,0x00,0x20,0x60,0x20,0x20,0x20,0x70,0x00,0x70,
0x88,0x08,0x70,0x80,0xf8,0x00,0xf8,0x10,0x30,0x08,0x88,0x70,0x00,0x20,0x40,0x90,
0x90,0xf8,0x10,0x00,0xf8,0x80,0xf0,0x08,0x88,0x70,0x00,0x70,0x80,0xf0,0x88,0x88,
0x70,0x00,0xf8,0x08,0x10,0x20,0x20,0x20,0x00,0x70,0x88,0x70,0x88,0x88,0x70,0x00,
0x70,0x88,0x88,0x78,0x08,0x70,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x30,0x30,
0x00,0x30,0x10,0x20,0x00,0x00,0x10,0x20,0x40,0x20,0x10,0x00,0x00,0xf8,0x00,0xf8,
0x00,0x00,0x00,0x00,0x20,0x10,0x08,0x10,0x20,0x00,0x70,0x88,0x10,0x20,0x00,0x20,
0x00,0x70,0x90,0xa8,0xb8,0x80,0x70,0x00,0x70,0x88,0x88,0xf8,0x88,0x88,0x00,0xf0,
0x88,0xf0,0x88,0x88,0xf0,0x00,0x70,0x88,0x80,0x80,0x88,0x70,0x00,0xe0,0x90,0x88,
0x88,0x90,0xe0,0x00,0xf8,0x80,0xf0,0x80,0x80,0xf8,0x00,0xf8,0x80,0xf0,0x80,0x80,
0x80,0x00,0x70,0x88,0x80,0x98,0x88,0x70,0x00,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,
0x70,0x20,0x20,0x20,0x20,0x70,0x00,0x10,0x10,0x10,0x10,0x90,0x60,0x00,0x90,0xa0,
0xc0,0xa0,0x90,0x88,0x00,0x80,0x80,0x80,0x80,0x80,0xf8,0x00,0x88,0xd8,0xa8,0x88,
0x88,0x88,0x00,0x88,0xc8,0xa8,0x98,0x88,0x88,0x00,0x70,0x88,0x88,0x88,0x88,0x70,
0x00,0xf0,0x88,0x88,0xf0,0x80,0x80,0x00,0x70,0x88,0x88,0xa8,0x98,0x70,0x00,0xf0,
0x88,0x88,0xf0,0x90,0x88,0x00,0x70,0x80,0x70,0x08,0x88,0x70,0x00,0xf8,0x20,0x20,
0x20,0x20,0x20,0x00,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x88,0x88,0x88,0x88,0x50,
0x20,0x00,0x88,0x88,0x88,0xa8,0xa8,0x50,0x00,0x88,0x50,0x20,0x20,0x50,0x88,0x00,
0x88,0x50,0x20,0x20,0x20,0x20,0x00,0xf8,0x10,0x20,0x40,0x80,0xf8,0x00,0x60,0x40,
0x40,0x40,0x40,0x60,0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x30,0x10,0x10,0x10,
0x10,0x30,0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,
0x00,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8};
/**************************************************************************
* put_char *
* Print char *
**************************************************************************/
void put_char(int x ,int y,int ascii_char ,byte color){
__asm__(
"push %si\n\t"
"push %di\n\t"
"push %cx\n\t"
"mov color,%dl\n\t" //test color
"mov ascii_char,%al\n\t" //test char
"sub $32,%al\n\t"
"mov $7,%ah\n\t"
"mul %ah\n\t"
"lea $characters,%si\n\t"
"add %ax,%si\n\t"
"mov $7,%cl\n\t"
"0:\n\t"
"segCS %lodsb\n\t"
"mov $6,%ch\n\t"
"1:\n\t"
"shl $1,%al\n\t"
"jnc 2f\n\t"
"mov %dl,%ES:(%di)\n\t"
"2:\n\t"
"inc %di\n\t"
"dec %ch\n\t"
"jnz 1b\n\t"
"add $320-6,%di\n\t"
"dec %cl\n\t"
"jnz 0b\n\t"
"pop %cx\n\t"
"pop %di\n\t"
"pop %si\n\t"
"retn"
);
}
Operand mismatch type for 'lea'
No such instruction 'segcs lodsb'
No such instruction 'retn'
/**************************************************************************
* put_char *
* Print char *
**************************************************************************/
void put_char(int x,int y){
int char_offset;
int l,i,j,h,offset;
j,h,l,i=0;
offset = (y<<8) + (y<<6) + x;
__asm__(
"movl _VGA, %%ebx;" // VGA memory pointer
"addl %%ebx,%%edi;" //%di points to screen
"mov _ascii_char,%%al;"
"sub $32,%%al;"
"mov $7,%%ah;"
"mul %%ah;"
"lea _characters,%%si;"
"add %%ax,%%si;" //SI point to bitmap
"mov $7,%%cl;"
"0:;"
"lodsb %%cs:(%%si);" //load next byte of bitmap
"mov $6,%%ch;"
"1:;"
"shl $1,%%al;"
"jnc 2f;"
"movb %%dl,(%%edi);" //plot the pixel
"2:\n\t"
"incl %%edi;"
"dec %%ch;"
"jnz 1b;"
"addl $320-6,%%edi;"
"dec %%cl;"
"jnz 0b;"
: "=D" (offset)
: "d" (current_color)
);
}
最佳答案
请参阅下文,以分析某些put_char
函数特别有问题的地方,以及可能起作用的版本。 (我不确定%cs
段覆盖是否正确,但除此之外,它应该可以实现您的预期)。
学习DOS和16位asm并不是学习asm的最佳方法
首先,DOS和16位x86已经过时,并且不比普通的64位x86更容易学习。即使32位x86也已过时,但在Windows世界中仍被广泛使用。
32位和64位代码不必关心很多16位限制/复杂性,例如段或寻址模式中有限的寄存器选择。一些现代系统确实使用段替代来进行线程本地存储,但是,学习如何在16位代码中使用段几乎没有联系。
了解asm的主要好处之一是调试/分析/优化实际程序。如果您想了解如何编写C或其他高级代码that can (and actually does) compile to efficient asm,您可能会成为looking at compiler output。这将是64位(或32位)。 (例如,请参阅Matt Godbolt的CppCon2017演讲:“What Has My Compiler Done for Me Lately? Unbolting the Compiler's Lid”,该书为入门的初学者阅读x86 asm以及介绍编译器输出提供了很好的介绍)。
在查看性能计数器结果并注释二进制文件的反汇编时,Asm知识非常有用(perf stat ./a.out
&& perf report -Mintel
:参见Chandler Carruth's CppCon2015 talk: "Tuning C++: Benchmarks, and CPUs, and Compilers! Oh My!")。激进的编译器优化意味着,与每条指令相比,查看每条源代码行的周期/缓存丢失/停顿计数所提供的信息少得多。
另外,要使您的程序实际执行任何操作,它必须直接与硬件对话或进行系统调用。学习DOS系统需要文件访问和用户输入,这完全是浪费时间(除了回答有关如何读取和打印16位代码中的多位数数字的源源不断的SO问题)。它们与当前主要操作系统中的API完全不同。开发新的DOS应用程序无济于事,因此,当您要掌握使用asm知识进行操作的阶段时,您必须学习其他API(以及ABI)。
在8086模拟器上学习asm的限制更大:186、286和386添加了许多方便的指令,例如imul ecx, 15
,从而使ax
的“特殊性”降低了。将自己限制在仅适用于8086的指令上意味着您将找出做事的“不好”方法。其他较大的变量是movzx
/ movsx
,立即移位(除1之外)和push immediate
。除了性能之外,在可用时编写代码也更加容易,因为您不必编写循环来移位多于1位。
有关更好地教自己asm的建议
我主要通过阅读编译器输出来学习asm,然后进行一些小的更改。当我不太了解内容时,我并没有尝试在asm中编写东西,但是,如果您要快速学习(而不是仅在调试/分析C时形成理解),则可能需要通过以下方法测试您的理解:编写自己的代码。您确实需要了解基本知识,有8或16个整数寄存器+标志和指令指针,并且每条指令都对计算机的当前体系结构状态进行了明确定义的修改。 (有关每条指令的完整说明,请参阅Intel insn ref手册(x86 Wiki中的链接以及更多有用的内容)。
您可能想从简单的事情开始,例如在更大的程序中用asm编写单个函数。了解进行系统调用所需的asm类型很有用,但是在实际程序中,通常只为不涉及任何系统调用的内部循环手写asm才有用。编写asm来读取输入和打印结果非常耗时,因此我建议在C语言中进行此操作。请确保您阅读了编译器的输出,并了解发生了什么,整数与字符串之间的区别以及strtol
和printf
可以,即使您自己不写它们。
一旦您认为您对基础知识已经足够了解,就可以在您熟悉和/或感兴趣的某个程序中找到一个函数,并查看是否可以击败编译器并保存指令(或使用更快的指令)。或者您自己实现它,而不以编译器输出为起点,以您发现更有趣的为准。 This answer可能很有趣,尽管那里的重点是找到使编译器产生最佳ASM的C源代码。
如何尝试解决自己的问题(问一个SO问题之前)
人们有很多SO问题,问“我如何在asm中执行X”,答案通常是“与在C中相同”。不要被不熟悉的asm所困扰,而忘记了如何编程。弄清楚该函数所操作的数据需要做什么,然后弄清楚如何在asm中进行操作。如果您陷入困境并不得不提出问题,那么您应该拥有大部分有效的实施方案,只有一部分您不知道要在哪一步中使用什么指令。
您应该使用32或64位x86。我建议使用64位,因为ABI更好,但是32位功能将迫使您更多地使用堆栈。因此,这可能有助于您了解call
指令如何将返回地址放置在堆栈上,以及调用方实际推入的args在此之后。 (这似乎是您尝试使用内联asm避免处理的内容)。
直接对硬件进行编程很整洁,但不是一般有用的技能
通过直接修改视频RAM来学习如何做图形,除了满足人们对计算机过去工作方式的好奇心外,是没有用的。您不能将这些知识用于任何事情。现代图形API的存在是为了让多个程序可以在自己的屏幕区域中绘画并允许间接调用(例如,直接在纹理而不是屏幕上绘画,因此3D窗口翻转alt选项卡看起来不错)。这里有太多的原因要列出而不直接在视频RAM上绘制。
可以在像素图缓冲区上绘图,然后使用图形API将其复制到屏幕上。不过,除非要为PNG或JPEG等生成图像(例如,将Web后端代码中的直方图bin转换为散点图进行优化,否则完全不做位图图形)。现代图形API抽象化了分辨率,因此您的应用程序可以以合理的大小绘制图形,而不管每个像素有多大。 (小屏幕但rez屏幕非常高,而rez屏幕大而低)。
写内存并在屏幕上看到某些变化是很酷的。甚至更好的是,将LED(带有小电阻器)连接到并行端口上的数据位,并运行outb
指令打开/关闭它们。我是在很久以前的Linux系统上执行此操作的。我编写了一个使用iopl(2)
和内联asm的包装程序,并以root身份运行它。您可能可以在Windows上执行类似操作。您不需要DOS或16位代码即可与硬件对话。in
/ out
指令以及对内存映射的IO和DMA的正常加载/存储是真正的驱动程序与硬件的通信方式,包括比并行端口复杂得多的事情。知道您的硬件“真正”如何工作很有趣,但是只有在您真正感兴趣或想要编写驱动程序时才花时间。 Linux源代码树包含用于加载大量硬件的驱动程序,并且经常被注释,因此,如果您既喜欢阅读代码,又喜欢编写代码,那是另一种感受读驱动程序与硬件对话时的方式的方式。
总体了解事情的幕后工作通常是一件好事。如果您想了解图形在过去如何工作(使用VGA文本模式和颜色/属性字节),那么请放心。请注意,现代操作系统不使用VGA文本模式,因此您甚至都不了解现代计算机的幕后情况。
许多人喜欢https://retrocomputing.stackexchange.com/,这使计算机不那么复杂并且无法支持那么多抽象层,从而使工作时间更短。请注意,这就是您在做什么。如果您确定这就是为什么要了解asm /硬件,那么我可能是学习编写现代硬件驱动程序的一个很好的垫脚石。
内联汇编
您使用完全错误的方法来使用嵌入式ASM。您似乎想在asm中编写整个函数,因此您应该这样做。例如将您的代码放入asmfuncs.S
之类的东西中。如果要继续使用GNU / AT&T语法,请使用.S
;否则,请使用.asm
。或使用%ebx
(如果您想使用Intel / NASM / YASM语法)(我建议这样做,因为官方手册都使用Intel语法。有关指南和手册,请参见x86 Wiki)。
GNU内联汇编是学习ASM的最困难的方法。您必须了解asm所做的一切,以及编译器需要了解的内容。很难正确解决所有问题。例如,在您的编辑中,该内联汇编代码块修改了许多您没有列出的寄存器,包括ret
这是一个调用保留的寄存器(因此即使未内联该函数,它也会被破坏)。至少您取出了put_char
,所以当编译器将该函数内联到调用它的循环中时,事情不会中断得那么厉害。如果这听起来真的很复杂,那是因为它是,这也是为什么您不应该使用嵌入式asm学习asm的部分原因。
This answer to a similar question from misusing inline asm while trying to learn asm in the first place有更多关于内联汇编以及如何使用它的链接。
使这个混乱工作,也许
这部分可能是一个单独的答案,但我将其保留在一起。
除了整个方法从根本上来说不是一个好主意外,offset
函数还存在至少一个特定问题:您将ret
用作仅输出操作数。 gcc非常高兴地将整个函数编译为一条volatile
指令,因为asm语句不是volatile
,并且不使用其输出。 (不带输出的嵌入式asm语句假定为-m16
。)
我put your function on godbolt,所以我可以看看编译器围绕它生成的程序集。该链接指向固定的可能工作的版本,带有正确声明的Clobber,注释,清理和优化。如果该外部链接中断,请参见下面的相同代码。
我将gcc 5.3与int
选项一起使用,这与使用真正的16位编译器不同。它仍然以32位方式(在堆栈上使用32位地址,32位-O0
和32位函数args)执行所有操作,但告诉汇编器CPU将处于16位模式,因此它将知道何时发出操作数大小和地址大小前缀。
即使您compile your original version with offset = (y<<8) + (y<<6) + x;
,编译器也会计算%edi
,但不会将其放在%edi
中,因为您没有要求它。将其指定为另一个输入操作数将起作用。内联汇编之后,它将-12(%ebp)
存储到offset
所在的put_char
中。ascii_char
的其他错误:
您通过全局变量而不是函数参数将2个东西(current_color
和VGA
)传递给函数。 uck,真恶心。 characters
和offset
是常量,因此从全局变量加载它们看起来并不那么糟糕。使用asm编写意味着您仅应在良好的性能帮助下才忽略良好的编码习惯。由于调用者可能必须将这些值存储到全局变量中,因此与将它们作为函数args存储在堆栈中的调用者相比,您无需保存任何内容。对于x86-64,您将失去性能,因为调用者可以将它们传递到寄存器中。
也:
j,h,l,i=0; // sets i=0, does nothing to j, h, or l.
// gcc warns: left-hand operand of comma expression has no effect
j;h;l;i=0; // equivalent to this
j=h=l=i=0; // This is probably what you meant
characters
以外,所有局部变量都未使用。您要用C或其他语言编写它吗?
CS:
,但将32位寻址模式用于VGA内存。我认为这是故意的,但我不知道它是否正确。另外,您确定应该对
characters
的负载使用
.rodata
替代吗?
uint8_t characters[464]
部分是否进入代码段?尽管您没有将
const
声明为
.data
,但是无论如何它都可能只是在
%ebx
部分中。我认为自己很幸运,虽然我实际上没有为分段内存模型编写代码,但是看起来仍然很可疑。
%ebx
,而不是加载到ebx中,然后在
%edi
中添加
lea
。
"add _VGA, %%edi\n\t" // load from _VGA, add to edi.
$_characters
将地址保存到寄存器中。你可以用
"mov %%ax, %%si\n\t"
"add $_characters, %%si\n\t"
characters
表示地址为立即数。通过将其与以前的偏移量计算组合到位图的
imul
数组中,我们可以节省很多指令。
%si
的立即操作数形式使我们首先在
imul
中产生结果:
"movzbw _ascii_char,%%si\n\t"
//"sub $32,%%ax\n\t" // AX = ascii_char - 32
"imul $7, %%si, %%si\n\t"
"add $(_characters - 32*7), %%si\n\t" // Do the -32 at the same time as adding the table address, after multiplying
// SI points to characters[(ascii_char-32)*7]
// i.e. the start of the bitmap for the current ascii character.
imul
仅保持16 * 16-> 32b的低16b乘以
the 2 and 3 operand forms imul
can be used for signed or unsigned multiplies,这就是为什么只有
mul
(不是
imul
)具有那些额外形式的原因。对于较大的操作数大小乘法,请使用2和3操作数
%[er]dx
is faster,因为它不必将高半部分存储在
shl $1, %al
中。
%edi
设置),而不使用计数器。这也将使其变得不可预测,就像非前景像素的跳转存储一样,因此增加的分支错误预测可能比多余的虚无循环还要糟糕。这也意味着您每次都需要在外循环中重新计算
{7 6 5 4 3 2 1 0}
,因为内循环不会运行恒定的次数。但它看起来像:
... same first part of the loop as before
// re-initialize %edi to first_pixel-1, based on outer-loop counter
"lea -1(%%edi), %%ebx\n"
".Lbit_loop:\n\t" // map the 1bpp bitmap to 8bpp VGA memory
"incl %%ebx\n\t" // inc before shift, to preserve flags
"shl $1,%%al\n\t"
"jnc .Lskip_store\n\t" // transparency: only store on foreground pixels
"movb %%dl,(%%ebx)\n" //plot the pixel
".Lskip_store:\n\t"
"jnz .Lbit_loop\n\t" // flags still set from shl
"addl $320,%%edi\n\t" // WITHOUT the -6
"dec %%cl\n\t"
"jnz .Lbyte_loop\n\t"
mov
之类的VGA内存中的字节,因为您正在测试左移的位。因此,它从MSB开始。寄存器中的位始终是“大端”。即使在像x86这样的低端机器上,左移也乘以2。小尾数仅影响存储器中字节的顺序,不影响字节中的位,甚至不影响寄存器中的字节。
void put_char(int x,int y){
int offset = (y<<8) + (y<<6) + x;
__asm__ volatile ( // volatile is implicit for asm statements with no outputs, but better safe than sorry.
"add _VGA, %%edi\n\t" // edi points to VGA + offset.
"movzbw _ascii_char,%%si\n\t" // Better: use an input operand
//"sub $32,%%ax\n\t" // AX = ascii_char - 32
"imul $7, %%si, %%si\n\t" // can't fold the load into this because it's not zero-padded
"add $(_characters - 32*7), %%si\n\t" // Do the -32 at the same time as adding the table address, after multiplying
// SI points to characters[(ascii_char-32)*7]
// i.e. the start of the bitmap for the current ascii character.
"mov $7,%%cl\n"
".Lbyte_loop:\n\t"
"lodsb %%cs:(%%si)\n\t" //load next byte of bitmap
"mov $6,%%ch\n"
".Lbit_loop:\n\t" // map the 1bpp bitmap to 8bpp VGA memory
"shl $1,%%al\n\t"
"jnc .Lskip_store\n\t" // transparency: only store on foreground pixels
"movb %%dl,(%%edi)\n" //plot the pixel
".Lskip_store:\n\t"
"incl %%edi\n\t"
"dec %%ch\n\t"
"jnz .Lbit_loop\n\t"
"addl $320-6,%%edi\n\t"
"dec %%cl\n\t"
"jnz .Lbyte_loop\n\t"
:
: "D" (offset), "d" (current_color)
: "%eax", "%ecx", "%esi", "memory"
// omit the memory clobber if your C never touches VGA memory, and your asm never loads/stores anywhere else.
// but that's not the case here: the asm loads from memory written by C
// without listing it as a memory operand (even a pointer in a register isn't sufficient)
// so gcc might optimize away "dead" stores to it, or reorder the asm with loads/stores to it.
);
}
offset
说明)。例如,这里不需要强制编译器将
%edi
放在
关于c - 使用GNU C内联汇编在VGA内存中绘制字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34748733/
我有数百个文件,命名如下: RG1-t.txt RG1-n.txt RG2-t.txt RG2-n.txt 等等... 我想使用GNU并行在它们上运行脚本,但是我很难获得文件的基本名称,因此RG1,R
从例子 seq 1 100 | parallel -I @@ \ > 'mkdir top-@@;seq 1 100 | parallel -X mkdir top-@@/sub-{} 怎么办-X ,
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
我有一个简单的 Makefile: VAR := aaa include a.inc VAR += bbb 和a.inc some_target: $(VAR) @echo "refe
按照指南制作新类(class)。我可以使用 gst 命令制作新的或加载图像文件 (.im)。我输入代码来创建一个 Account 类,然后可以创建一个新类。 问题如何在关闭 gst 窗口之前将类保存到
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 10年前关闭。 Improve this
我想使用 GNU screen 来监视这样的串行 USB 端口: $ screen /dev/ttyUSB0 115200 但我需要调整一些终端线路设置。我已经进行了几次尝试,但似乎都没有奏效。例如,
我已阅读全文 documentation对于 gnu 排序和在线搜索,但我找不到 --buffer-size 选项的默认值是什么(它决定了程序在运行时使用多少系统内存)。我猜它是根据系统总内存以某种方
我正在使用 parallel --keep-order --line-buffer --halt 2 在一堆命令上并行调用 GNU .每隔一段时间,其中一个命令就会失败,并且 GNU 并行打印: p
这个问题与问题 2543127 的精神相似。 . 我有一个带有头文件列表的 gnu makefile。每个头文件可能位于不同的目录中,例如, HEADERS = $(wildcard *.h) $(w
假设我有以下 GNU make 目标: create_dir: @mkdir objects build_asm: $(ASM_FILES) @echo
默认情况下,当您在 GNU Screen 中创建新窗口时,它将在调用 Screen 的目录中启动。我想在当前所在窗口的当前工作目录的 GNU Screen 中启动一个新窗口。我该怎么做? 最佳答案 查
我想在几个输入上运行几个长时间运行的进程。例如。: solver_a problem_1 solver_b problem_1 ... solver_b problem_18 solver_c pro
很难说出这里问的是什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或言辞激烈,无法以目前的形式合理回答。如需帮助澄清此问题以便可以重新打开,visit the help center . 8年前关闭
我可以看到在多个输入上运行并行作业是多么容易,但是有没有其他方法可以通过将命令放入文件并重复多次来并行运行同一作业多次? parallel -j+0 ::: './dosomejob.sh' 但是告诉
所以我一直在尝试寻找一些关于 GNU screen 实际上如何在 high 下工作的信息,而不必真正阅读源代码,但我一直无法这样做。 screen 做了什么,即使在终端 session 关闭时它也能保
在调查崩溃时,我遇到了以下代码片段并立即意识到 mov 指令实际上应该是 movq 以获得正确的 64 位寄存器操作。 #elif defined(__x86_64__) unsigned l
我安装了 indent使用 brew感谢命令 brew install gnu-indent所以现在我有 gnu-indent-2.2.10到目前为止安装在我的 MacOS X 上,非常好。我的问题是
考虑这个Makefile: .PHONY: all all: main.txt main.txt: build/main.txt cp build/main.txt . %/main.txt:
假设目录输入中有 1000 个扩展名为 .xhtml 的文件,并且这些文件的某个子集(输出路径在 $(FILES) 中)需要通过 xslt 转换为目录输出中具有相同名称的文件.一个简单的 make 规
我是一名优秀的程序员,十分优秀!