我一直认为printf()在最后一步中使用内联汇编定义函数.在stdio.h的内部深处埋藏了一些asm代码,它实际上告诉CPU要做什么.例如,在dos中,我记得它是通过首先mov将字符串的开头添加到某个内存位置或寄存器而不是调用intterupt来实现的.
但是,由于Visual Studio的x64版本根本不支持内联汇编程序,因此我想知道在C/C++中根本不会有汇编程序定义的函数.库函数如何printf()在不使用汇编代码的情况下在C/C++中实现?什么实际执行正确的软件中断?谢谢.
在实现无锁数据结构和时序代码时,通常需要抑制编译器的优化.通常人们在clobber列表中使用asm volatilewith memory,但你有时会看到asm volatile或只是一个简单的asm破坏性记忆.
这些不同的陈述对代码生成有什么影响(特别是在GCC中,因为它不太可能是可移植的)?
仅供参考,这些是有趣的变化:
asm (""); // presumably this has no effect on code generation
asm volatile ("");
asm ("" ::: "memory");
asm volatile ("" ::: "memory");
Run Code Online (Sandbox Code Playgroud) 该compare函数是一个函数,它接受两个参数a,b并返回一个描述其顺序的整数.如果a小于b,则结果为负整数.如果a大于b,则结果为正整数.否则,a并且b相等,结果为零.
此功能通常用于参数化标准库中的排序和搜索算法.
实现compare字符功能非常简单; 你只需减去参数:
int compare_char(char a, char b)
{
return a - b;
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为通常假设两个字符之间的差异适合整数.(请注意,此假设不适用于以下系统sizeof(char) == sizeof(int).)
这个技巧无法比较整数,因为两个整数之间的差异通常不适合整数.例如,INT_MAX - (-1) = INT_MIN建议INT_MAX小于-1(技术上,溢出导致未定义的行为,但让我们假设模运算).
那么我们如何才能有效地为整数实现比较函数呢?这是我的第一次尝试:
int compare_int(int a, int b)
{
int temp;
int result;
__asm__ __volatile__ (
"cmp %3, %2 \n\t"
"mov $0, %1 \n\t"
"mov $1, %0 \n\t"
"cmovg %0, %1 …Run Code Online (Sandbox Code Playgroud) 我想写一个小的低级程序.对于它的某些部分,我将需要使用汇编语言,但其余代码将使用C/C++编写.
那么,如果我使用GCC将C/C++与汇编代码混合在一起,我是否需要使用AT&T语法,还是可以使用Intel语法?或者你如何以其他方式混合使用C/C++和asm(intel语法)?
我意识到也许我没有选择,必须使用AT&T语法,但我想确定..
如果结果没有选择,我可以在哪里找到有关AT&T语法的完整/官方文档?
谢谢!
我记得当天用旧的borland DOS编译器你可以做这样的事情:
asm {
mov ax,ex
etc etc...
}
Run Code Online (Sandbox Code Playgroud)
现在是否有半平台独立的方式来做到这一点?我需要进行BIOS调用,所以如果有一种方法可以在没有asm代码的情况下执行此操作,那对我来说同样有用.
我记得有一种方法可以使用扩展的gcc内联汇编来读取寄存器值并将其存储到C变量中.我不能为我的生活记住如何形成asm陈述.任何帮助深表感谢.
在我正在进行的GCC内联汇编实验中,我遇到了一个关于标签和内联代码的新问题.
考虑以下简单的跳转:
__asm__
(
"jmp out;"
"out:;"
:
:
);
Run Code Online (Sandbox Code Playgroud)
除了跳转到out标签外,这没有任何作用.这样,这段代码编译得很好.但是如果你把它放在一个函数中,然后用优化标志进行编译,编译器就会抱怨:"错误:符号'out'已经被定义了".
似乎正在发生的事情是编译器每次内联函数时都会重复此汇编代码.这会导致标签out重复,从而导致多个out标签.
那么,我该如何解决这个问题呢?在内联装配中是否真的不可能使用标签?关于GCC内联汇编的本教程提到:
因此,您可以将汇编放入CPP宏和内联C函数中,因此任何人都可以将其用作任何C函数/宏.内联函数非常类似于宏,但有时使用起来更干净.请注意,在所有这些情况下,代码将被复制,因此只应在该asm代码中定义本地标签(1:样式).
我试图找到有关这些"本地标签"的更多信息,但似乎无法找到与内联汇编有关的任何内容.看起来教程是说本地标签是一个数字后面跟冒号(比如1:),所以我尝试使用这样的标签.有趣的是,代码已编译,但在运行时它只是触发了分段错误.嗯...
那么任何建议,提示,答案......?
我查看了一些C代码
http://www.mcs.anl.gov/~kazutomo/rdtsc.html
他们使用像" 内联 "," asm "等东西,如下所示:
代码1:
static __inline__ tick gettick (void) {
unsigned a, d;
__asm__ __volatile__("rdtsc": "=a" (a), "=d" (d) );
return (((tick)a) | (((tick)d) << 32));
}
Run Code Online (Sandbox Code Playgroud)
码2:
volatile int __attribute__((noinline)) foo2 (int a0, int a1) {
__asm__ __volatile__ ("");
}
Run Code Online (Sandbox Code Playgroud)
我想知道code1和code2做了什么?
据我所知道的,唯一的区别__asm { ... };,并__asm__("...");是第一个使用mov eax, var第二个使用movl %0, %%eax与:"=r" (var)结尾.还有什么其他差异?那又怎么样asm?
与我的其他问题相关,请帮我调试"未知模块中发生未处理的类型'System.AccessViolationException'异常.附加信息:尝试读取或写入受保护的内存.这通常表明其他内存已损坏." 逐步执行代码,一切都会一直运行,直到实际调用del()并在该行中失败.
这段代码基于本文的示例和python代码,它在python中运行.我无法得到代码示例,因为它可以工作(相同的例外),但我希望它只是有点过时或者其他东西.
编辑:如果你关心我们如何到达这里,看看编辑历史,这是无趣的.
public static class CpuID
{
public static byte[] Invoke(int level)
{
IntPtr codePointer = IntPtr.Zero;
try
{
// compile
byte[] codeBytes;
if (IntPtr.Size == 4)
{
codeBytes = x86CodeBytes;
}
else
{
codeBytes = x64CodeBytes;
}
codePointer = VirtualAlloc(
IntPtr.Zero,
new UIntPtr((uint)codeBytes.Length),
AllocationType.COMMIT | AllocationType.RESERVE,
MemoryProtection.EXECUTE_READWRITE
);
Marshal.Copy(codeBytes, 0, codePointer, codeBytes.Length);
CpuIDDelegate cpuIdDelg = (CpuIDDelegate)Marshal.GetDelegateForFunctionPointer(codePointer, typeof(CpuIDDelegate));
// invoke
GCHandle handle = default(GCHandle);
var buffer = new byte[16];
try
{ …Run Code Online (Sandbox Code Playgroud)