How does a language expand itself?
Asked Answered
C

15

212

I am learning C++ and I've just started learning about some of Qt's capabilities to code GUI programs. I asked myself the following question:

How does C++, which previously had no syntax capable of asking the OS for a window or a way to communicate through networks (with APIs which I don't completely understand either, I admit) suddenly get such capabilities through libraries written in C++ themselves? It all seems terribly circular to me. What C++ instructions could you possibly come up with in those libraries?

I realize this question might seem trivial to an experienced software developer but I've been researching for hours without finding any direct response. It's gotten to the point where I can't follow the tutorial about Qt because the existence of libraries is incomprehensible to me.

Continuate answered 28/7, 2014 at 10:30 Comment(14)
How does std::cout even draw anything on the monitor? Or does it sit on top of a compiler which understands your hardware?Conch
Great question. Ultimately it's hard to answer until you study hardware.Person
See also: #9164054Eachern
Qt is not an expansion of the language (that would require a Qt-aware compiler). It is merely a library that's added to your arsenal. Eventually, at the lowest level all libraries communicate with the OS via system calls, which are independent of the language, but very much dependent on the OS and the CPU architecture.Chaqueta
afaik, C++ has inline assembly, which can do pretty much anythingJanijania
@DevSolar: Actually Qt does expand the language with its own signal-slot mechanism, reflection and many other dynamic features. And those things require a compiler (the meta-object compiler) to compile down to C++ code.Moten
@C.R.: Ah. Thanks for reminding me why I opted against Qt back in the day. ;-)Chaqueta
See also this question on Programmers - programmers.stackexchange.com/questions/105313/…Salivation
I love this question. It shows the kind of insightfulness that can only come from being clever and inexperienced at the same time, and it forces us oldtimers to remember to think outside the box. I wish you well in your programming career. This will make more sense as you grow more experienced, and perhaps then you can come back here and provide a better answer.Alkoran
Not strictly relevant, but I have always felt that the following fact is very cool: Say you want to create C++. You write a compiler using say assembly, and now you have a compiler that can compile C++ programs. Then you write a new compiler in C++ (and compile it using the compiler you have). Now discard the original compiler, and you have an entire system in C++! Another seemingly circular thing that's very cool imo.Pineapple
Interesting tidbit: The C++ compiler is written in C++. <insert xzibit meme here>Nub
@SargeBorsch assembler can do the same things c++ can (which is because c++ is just translated to assembler).Ailment
Sorry to spoil the fun, but how is this question on-topic?Doerr
@C.R. I'd say Qt does not really expand C++. Qt uses code generation based on markup (specific preprosessor macros) in C++ sources. The sources are still 100% valid C++.Hertzfeld
X
197

A computer is like an onion, it has many many layers, from the inner core of pure hardware to the outermost application layer. Each layer exposes parts of itself to the next outer layer, so that the outer layer may use some of the inner layers functionality.

In the case of e.g. Windows the operating system exposes the so-called WIN32 API for applications running on Windows. The Qt library uses that API to provide applications using Qt to its own API. You use Qt, Qt uses WIN32, WIN32 uses lower levels of the Windows operating system, and so on until it's electrical signals in the hardware.

Xylene answered 28/7, 2014 at 10:30 Comment(7)
Note: Qt here provides an abstraction of the layer below it, because on Linux Qt invokes the Linux API and not the WIN32 API.Sartre
I would probably elaboarte a little more on the example of Qt, that it just appears, like it effortlessly extends c++ capabilities. When the reality is, they put a lot of effort, to to make a common API, to (debatably) many different "onion cores". They are the ones providing portability on top of non-portable non-standard backends.Sedan
A computer is like an onion: cutting through it makes you cry, but it's somewhat tasty afterwards.Fenestra
@ChristopherPfohl Yeah, had to use it since I couldn't figure out how a computer would be like a box of chocolates. :)Xylene
I remember when I was first learning C++ the teacher said "if you want to do any work with GUIs on Windows you need to go through xyz.dll" what was the name of xyz? I guess frameworks such as Qt act as layers of abstraction to the dlls that actually get called in Windows.Embitter
In simple answer, when you create a language to run in computers, you have to give your users most capabilities to run as many functionality as possible. Computer & OS makers need to provide more APIs for programmers to play with it and invent. Take it as browsers and java-script, you refuse to play by the rule, you remain behind like IE.Hobnail
@Embitter the teacher probably said user32.dll, or possibly gdi32.dll.Gabler
C
61

You're right that in general, libraries cannot make anything possible that isn't already possible.

But the libraries don't have to be written in C++ in order to be usable by a C++ program. Even if they are written in C++, they may internally use other libraries not written in C++. So the fact that C++ didn't provide any way to do it doesn't prevent it from being added, so long as there is some way to do it outside of C++.

At a quite low level, some functions called by C++ (or by C) will be written in assembly, and the assembly contains the required instructions to do whatever isn't possible (or isn't easy) in C++, for example to call a system function. At that point, that system call can do anything your computer is capable of, simply because there's nothing stopping it.

Confection answered 28/7, 2014 at 10:41 Comment(10)
Do you mean those libraries written in the other languages are compiled already using other compilers ? And then there would have to be some sort of an interface file linking each function call provided to C++ by the library to a precompiled version of the library ? Thus allowing the C++ compiler to know what to translate those calls into ?Continuate
@MedLarbiSentissi 1) Not necessarily other compilers. It's possible (and it happens to be the case, often) that one single compiler is capable of compiling multiple languages, including assembly, and it may even be capable of compiling C++ with inline assembly. 2) Depending on the specific system and compiler, making those functions callable from C++ may indeed be done with some sort of an interface file, but that sort of interface file may already be a C (or even C++) header directly usable from C++.Confection
@MedLarbiSentissi: Many windows libraries are compiled into dll files which contain their own interface, as well as the code. You can peek into a dll and see a list of the functions that it lets you use. They often also come with a C header file. When you create your exe, it contains a list of dlls it needs to run. When the OS tries to load your exe, it will automatically also load those dlls before starting execution.Kilauea
This answer seems to suggest that the "magic" lies completely in other languages being called, but actually most of the code that constitutes most modern operating systems is C (with only very hardware-tied or performance-critical parts written in assembly) - and it's definitely possible to use C++ instead. The point is, there's no "magic", languages are created to build such powerful abstractions, and once you can interact with hardware the possibilities are almost limitless.Yvetteyvon
As C and C++ are languages that are compiled to actual processor instructions (aka assembly), theyre just another way to express assembly code, thus there is no real difference (on what is doable in the language) between inline-assembly, a language feature that translates into exactly that assembly, or handwriting a .dll with a hex editor containing the op-codes.Ailment
@Ailment assembly and C++ are not equivalent, there are processor features/opcodes (e.g. iret operation) for which there isn't "a language feature that translates into exactly that assembly", and you have to use [inline] assembly for that; and even for normal operations you might want generate for optimization some different assembly than what the compiler would generate and again there wouldn't be any language feature that translates into exactly that assembly.Thrave
@MatteoItalia You just need a few very basic very small building blocks that aren't written in C (or C++), and everything chaining them together can be C (or C++), that's right. But the magic is those very basic very small building blocks: without those, you'd be completely and hopelessly stuck.Confection
@Thrave I said that there is not difference between inline assembly and a feature that translates into exactly that assembly. This obv implies that said feature already exists. The point is that while a language X has a specification of what a compiler HAS to do (at least), it is actually the compiler that makes X do something and the compiler is as powerful as ASM itself. The whole point is that saying the language cannot do Y sound like the language would do something and cannot do Y,but in reality it just has no translation for Y, but any compiler for the language can add Y on its own willAilment
@Ailment Inline assembly is highly implementation-specific, and although implemented in every major C and C++ compiler, I wouldn't call it something you can do in C or in C++, you can do it in some particular vendor's implementation of their C or C++ compiler.Confection
@hvd I think the whole conflict in this discussion is that you (and others) define C as the features that are specified for it. In fact, compilers add a lot more than what is specified, making the question of what C is kinda non-trivial to answer. For me the special thing about a language (thus the thing that it is) is the meta-way to expresssprogram flow and the possibilities to structure. The elements that are structured are not important for it, as it is just nicer ASM-code that can be added by compilers as they wishAilment
W
43

C and C++ have 2 properties that allow all this extensibility that the OP is talking about.

  1. C and C++ can access memory
  2. C and C++ can call assembly code for instructions not in the C or C++ language.

In the kernel or in a basic non-protected mode platform, peripherals like the serial port or disk drive are mapped into the memory map in the same way as RAM is. Memory is a series of switches and flipping the switches of the peripheral (like a serial port or disk driver) gets your peripheral to do useful things.

In a protected mode operating system, when one wants to access the kernel from userspace (say when writing to the file system or to draw a pixel on the screen) one needs to make a system call. C does not have an instruction to make a system calls but C can call assembler code which can trigger the correct system call, This is what allows one's C code to talk to the kernel.

In order to make programming a particular platform easier, system calls are wrapped in more complex functions which may perform some useful function within one's own program. One is free to call the system calls directly (using assembler) but it is probably easier to just make use of one of the wrapper functions that the platform supplies.

There is another level of API that are a lot more useful than a system call. Take for example malloc. Not only will this call the system to obtain large blocks of memory but will manage this memory by doing all the book keeping on what is take place.

Win32 APIs wrap some graphic functionality with a common platform widget set. Qt takes this a bit further by wrapping the Win32 (or X Windows) API in a cross platform way.

Fundamentally though a C compiler turns C code into machine code and since the computer is designed to use machine code, you should expect C to be able to accomplish the lions share or what a computer can do. All that the wrapper libraries do is do the heavy lifting for you so that you don't have to.

Woodberry answered 28/7, 2014 at 13:45 Comment(10)
Caveat about #2: C and C++ can only feasibly call functions that adhere to a "calling convention" that the compiler understands and expects. (Assembly code can use any convention it likes, or even none at all -- so the code might not be callable directly.) Fortunately, every self-respecting compiler provides a built-in way to use the platform's common conventions. (Windows C compilers, for example, let you have/use functions that use the "cdecl", "stdcall", or "fastcall" conventions.) But the assembly code must use a convention the compiler knows, or C and C++ can't call it directly.Sherrod
Also: memory-mapped I/O is common, but not the whole story. PCs, for example, commonly address serial ports, disk drives, etc using the x86's "I/O ports", a whole different mechanism. (The video buffer is usually memory-mapped, but video modes etc are typically controlled via I/O ports.)Sherrod
@cHao: Of course the classic approach using INP and OUTP is getting edged out in favor of DMA; the PCI generation seems to do more with memory-mapped special function registers, now that there's a way to automatically map devices to non-overlapping regions and discover them from drivers, and less with I/O ports.Worldbeater
modern peripherals will use DMA for bulk data transfer but you will still program the DMA controller with addressable memoryWoodberry
@doron: Umm, you program the DMA controller via the I/O address space (not the memory space) on a PC, at least if you're sane. Modern x86 CPUs like to reorder memory accesses to improve performance. With MMIO, that can be disastrous...so you'd need to be careful to make those addresses uncacheabke and put serializing instructions in all the right places. OTOH, the x86 itself ensures that reads and writes to I/O space are done in program order. Which is why much of the important stuff is still done via I/O space (which is generally not accessible via a pointer), and probably always will be.Sherrod
As i think about it, you might be able to use a volatile pointer to do MMIO safely. I guess i've just never trusted volatile to do exactly the right thing in that regard.Sherrod
@Sherrod you do need to map the physical address for the periferal into the kernel's vitual address space and unless you are totally insane, you will make it non-cached, but once done, from a programming point of view, you will write to it just like you write to RAM. As far as the CPU is concerned, it is memory. And you will use volatile to ensure that the compiler makes no assumptions about the value at said address.Woodberry
@doron: Yeah, the more i think about it, the more it seems like volatile would do the right thing (assuming the compiler implemented it correctly). I guess that's how it'd be done anyway on platforms that don't have a separate I/O address space. (On x86, though, i don't think i've yet seen MMIO done outside of protected mode, other than writing to the VGA buffer. If your phrase "non-protected mode platform" is meant to describe non-x86 rather than x86-real-mode platforms, you might want to clarify.)Sherrod
@Sherrod take a look at the linux kernel source, device driver to write to MMIO. To be fair though, the actual write is normally done with an function name something like write_reg which implements the assembler str (or equivalent) instruction, however there is not reason why you couldn't do this in C code.Woodberry
@doron: The kernel runs in protected mode, though.Sherrod
M
23

Languages (like C++11) are specifications, on paper, usually written in English. Look inside the latest C++11 draft (or buy the costly final spec from your ISO vendor).

You generally use a computer with some language implementation (You could in principle run a C++ program without any computer, e.g. using a bunch of human slaves interpreting it; that would be unethical and inefficient)

Your C++ implementation general works above some operating system and communicate with it (using some implementation specific code, often in some system library). Generally that communication is done thru system calls. Look for instance into syscalls(2) for a list of system calls available on the Linux kernel.

From the application point of view, a syscall is an elementary machine instruction like SYSENTER on x86-64 with some conventions (ABI)

On my Linux desktop, the Qt libraries are above X11 client libraries communicating with the X11 server Xorg thru X Windows protocols.

On Linux, use ldd on your executable to see the (long) list of dependencies on libraries. Use pmap on your running process to see which ones are "loaded" at runtime. BTW, on Linux, your application is probably using only free software, you could study its source code (from Qt, to Xlib, libc, ... the kernel) to understand more what is happening

Macedonian answered 28/7, 2014 at 10:39 Comment(1)
For reference, ANSI sells the C++11 spec for the slightly less outrageous price of US$60. (It used to be half that, but inflation. :P ) It's labeled as INCITS/ISO/IEC 14882, but it's at least the same base spec ISO offers. Not sure about errata/TRs.Sherrod
C
19

I think the concept you are missing is system calls. Each operating system provides an enormous amount of resources and functionality that you can tap into to do low-level operating system related things. Even when you call a regular library function, it is probably making a system call behind the scenes.

System calls are a low-level way of making use of the power of the operating system, but can be complex and cumbersome to use, so are often "wrapped" in APIs so that you don't have to deal with them directly. But underneath, just about anything you do that involves O/S related resources will use system calls, including printing, networking and sockets, etc.

In the case of windows, Microsoft Windows has its GUI actually written into the kernel, so there are system calls for making windows, painting graphics, etc. In other operating systems, the GUI may not be a part of the kernel, in which case as far as I know there wouldn't be any system calls for GUI related things, and you could only work at an even lower level with whatever low-level graphics and input related calls are available.

Calotte answered 28/7, 2014 at 23:37 Comment(1)
Important thing that is missing is that those system calls are by no means magic. They are serviced by kernel which is typically written in C(++). Moreover, syscalls are not even necessary. In rudimentary OS without memory protection, windows could be drawn by putting pixels directly into hardware framebuffer.Mirella
S
15

Good question. Every new C or C++ developer has this in mind. I am assuming a standard x86 machine for the rest of this post. If you are using Microsoft C++ compiler, open your notepad and type this (name the file Test.c)

int main(int argc, char **argv)
{
   return 0
}

And now compile this file (using developer command prompt) cl Test.c /FaTest.asm

Now open Test.asm in your notepad. What you see is the translated code - C/C++ is translated to assembler. Do you get the hint ?

_main   PROC
    push    ebp
    mov ebp, esp
    xor eax, eax
    pop ebp
    ret 0
_main   ENDP

C/C++ programs are designed to run on the metal. Which means they have access to lower level hardware which makes it easier to exploit the capabilities of the hardware. Say, I am going to write a C library getch() on a x86 machine.

Depending on the assembler I would type something this way :

_getch proc 
   xor AH, AH
   int 16h
   ;AL contains the keycode (AX is already there - so just return)
ret

I run it over with an assembler and generate a .OBJ - Name it getch.obj.

I then write a C program (I dont #include anything)

extern char getch();

void main(int, char **)
{
  getch();
}

Now name this file - GetChTest.c. Compile this file by passing getch.obj along. (Or compile individually to .obj and LINK GetChTest.Obj and getch.Obj together to produce GetChTest.exe).

Run GetChTest.exe and you would find that it waits for the keyboard input.

C/C++ programming is not just about language. To be a good C/C++ programmer you need to have a good understanding on the type of machine that it runs. You will need to know how the memory management is handled, how the registers are structured, etc., You may not need all these information for regular programming - but they would help you immensely. Apart from the basic hardware knowledge, it certainly helps if you understand how the compiler works (ie., how it translates) - which could enable you to tweak your code as necessary. It is an interesting package!

Both languages support __asm keyword which means you could mix your assembly language code too. Learning C and C++ will make you a better rounded programmer overall.

It is not necessary to always link with Assembler. I had mentioned it because I thought that would help you understand better. Mostly, most such library calls make use of system calls / APIs provided by the Operating System (the OS in turn does the hardware interaction stuff).

Stereotomy answered 29/7, 2014 at 11:45 Comment(0)
E
11

How does C++ ... suddenly get such capabilities through libraries written in C++ themselves ?

There's nothing magical about using other libraries. Libraries are simple big bags of functions that you can call.

Consider yourself writing a function like this

void addExclamation(std::string &str)
{
    str.push_back('!');
}

Now if you include that file you can write addExclamation(myVeryOwnString);. Now you might ask, "how did C++ suddenly get the capability to add exclamation points to a string?" The answer is easy: you wrote a function to do that then you called it.

So to answer your question about how C++ can get capabilities to draw windows through libraries written in C++, the answer is the same. Someone else wrote function(s) to do that, and then compiled them and gave them to you in the form of a library.

The other questions answer how the window drawing actually works, but you sounded confused about how libraries work so I wanted to address the most fundamental part of your question.

Ender answered 29/7, 2014 at 5:20 Comment(0)
B
8

The key is the possibility of the operating system to expose an API and a detailed description on how this API is to be used.

The operating system offers a set of APIs with calling conventions. The calling convention is defining the way a parameter is given into the API and how results are returned and how to execute the actual call.

Operating systems and the compilers creating code for them play nicely together, so you usually have not to think about it, just use it.

Bryce answered 28/7, 2014 at 10:36 Comment(0)
M
7

There is no need for a special syntax for creating windows. All that is required is that the OS provides an API to create windows. Such an API consists of simple function calls for which C++ does provide syntax.

Furthermore C and C++ are so called systems programming languages and are able to access arbitrary pointers (which might be mapped to some device by the hardware). Additionally, it is also fairly simple to call functions defined in assembly, which allows the full range of operations the processor provides. Therefore it is possible to write an OS itself using C or C++ and a small amount of assembly.

It should also be mentioned that Qt is a bad example, as it uses a so-called meta compiler to extend C++' syntax. This is however not related to it's ability to call into the APIs provided by the OS to actually draw or create windows.

Malamud answered 28/7, 2014 at 10:39 Comment(0)
P
7

First, there's a little misunderstading, I think

How does C++, which previously had no syntax capable of asking the OS for a window or a way to communicate through networks

There is no syntax for doing OS operations. It's the question of semantics.

suddenly get such capabilities through libraries written in C++ themselves

Well, the operating system is writen mostly in C. You can use shared libraries (so, dll) to call the external code. Additionally, the operating system code can register system routines on syscalls* or interrupts which you can call using assembly. That shared libraries often just make that system calls for you, so you are spared using inline assembly.

Here's the nice tutorial on that: http://www.win.tue.nl/~aeb/linux/lk/lk-4.html
It's for Linux, but the principles are the same.

How the operating system is doing operations on graphic cards, network cards etc? It's a very broad thema, but mostly you need to access interrupts, ports or write some data to special memory region. Since that operations are protected, you need to call them through the operating system anyway.

Pell answered 29/7, 2014 at 9:24 Comment(0)
H
7

In an attempt to provide a slightly different view to other answers, I shall answer like this.

(Disclaimer: I am simplifying things slightly, the situation I give is purely hypothetical and is written as a means of demonstrating concepts rather than being 100% true to life).

Think of things from the other perspective, imagine you've just written a simple operating system with basic threading, windowing and memory management capabilities. You want to implement a C++ library to let users program in C++ and do things like make windows, draw onto windows etc. The question is, how to do this.

Firstly, since C++ compiles to machine code, you need to define a way to use machine code to interface with C++. This is where functions come in, functions accept arguments and give return values, thus they provide a standard way of transferring data between different sections of code. They do this by establishing something known as a calling convention.

A calling convention states where and how arguments should be placed in memory so that a function can find them when it gets executed. When a function gets called, the calling function places the arguments in memory and then asks the CPU to jump over to the other function, where it does what it does before jumping back to where it was called from. This means that the code being called can be absolutely anything and it will not change how the function is called. In this case however, the code behind the function would be relevant to the operating system and would operate on the operating system's internal state.

So, many months later and you've got all your OS functions sorted out. Your user can call functions to create windows and draw onto them, they can make threads and all sorts of wonderful things. Here's the problem though, your OS's functions are going to be different to Linux's functions or Windows' functions. So you decide you need to give the user a standard interface so they can write portable code. Here is where QT comes in.

As you almost certainly know, QT has loads of useful classes and functions for doing the sorts of things that operating systems do, but in a way that appears independent of the underlying operating system. The way this works is that QT provides classes and functions that are uniform in the way they appear to the user, but the code behind the functions is different for each operating system. For example QT's QApplication::closeAllWindows() would actually be calling each operating system's specialised window closing function depending on the version used. In Windows it would most likely call CloseWindow(hwnd) whereas on an os using the X Window System, it would potentially call XDestroyWindow(display,window).

As is evident, an operating system has many layers, all of which have to interact through interfaces of many varieties. There are many aspects I haven't even touched on, but to explain them all would take a very long time. If you are further interested in the inner workings of operating systems, I recommend checking out the OS dev wiki.

Bear in mind though that the reason many operating systems choose to expose interfaces to C/C++ is that they compile to machine code, they allow assembly instructions to be mixed in with their own code and they provide a great degree of freedom to the programmer.

Again, there is a lot going on here. I would like to go on to explain how libraries like .so and .dll files do not have to be written in C/C++ and can be written in assembly or other languages, but I feel that if I add any more I might as well write an entire article, and as much as I'd love to do that I don't have a site to host it on.

Harner answered 30/7, 2014 at 10:5 Comment(0)
P
6

When you try to draw something on the screen, your code calls some other piece of code which calls some other code (etc.) until finally there is a "system call", which is a special instruction that the CPU can execute. These instructions can be either written in assembly or can be written in C++ if the compiler supports their "intrinsics" (which are functions that the compiler handles "specially" by converting them into special code that the CPU can understand). Their job is to tell the operating system to do something.

When a system call happens, a function gets called that calls another function (etc.) until finally the display driver is told to draw something on the screen. At that point, the display driver looks at a particular region in physical memory which is actually not memory, but rather an address range that can be written to as if it were memory. Instead, however, writing to that address range causes the graphics hardware to intercept the memory write, and draw something on the screen.
Writing to this region of memory is something that could be coded in C++, since on the software side it's just a regular memory access. It's just that the hardware handles it differently.
So that's a really basic explanation of how it can work.

Person answered 28/7, 2014 at 10:42 Comment(10)
Afaik a systemcall is not really a cpu instruction, and has nothing to do with intrinsics. Its more a function of the operating system kernel, which communicates with the devices.Lelialelith
@MatthiasB: Well, you're wrong, since syscall (and its cousin sysenter) is indeed a CPU instruction.Person
Sorry, then I misinterpreted your answer. For me it sounded like each command has its own systemcall. Syscall exists of course, but simplified it just switches to kernelmode and executes the kernel function.Lelialelith
@MatthiasB: Well it should be fairly obvious to anyone who knows what's really going on that this answer (and any other that actually fits on the screen) is necessarily way over-over-over-(did I say over-?)simplified. I certainly don't need a lecture on the topic myself; I know enough about it for my needs. As for the OP, if you think you can post a better answer that doesn't end up being as long as an entire book, go for it. I do think it's a little unfair to pick on my answer when there's entire books written about this topic that I necessarily have to summarize in a handful of paragraphs.Person
This was merely a hint to improve your answer, as it wasn't clear for myself. Don't see it as personal attack or anything.Lelialelith
@MatthiasB: I'm not taking it personally. I'm saying I already know the answer isn't factually 100% accurate but I think it's a good enough simplification to answer the OP -- so, if you actually know of a way to write a better answer then please either write your own answer or take the time to edit mine. I really don't have anything to add that I think is worth it, so if you want to see something better on this page you'll have to put in the effort yourself.Person
@Mehrdad I'm interested in the books you're talking about. Any recommendations ? Superficial understanding really bugs me.Continuate
@MedLarbiSentissi: If you really want a book, I guess here's one (among the millions out there) to get you started. I'm by no means claiming it's sufficient or interesting though. You might find the OSDev website more interesting.Person
System calls are done using software interrupts. Instructions like sysenter are optimized call paths, since the context switching used by interrupt handlers wasn't as fast as everyone desired, but fundamentally it's still a software generated interrupt while is handled by vectoring to a handler installed by the OS kernel. Part of the context switching process that IS performed by sysenter is changing the mode bits in the processor to set ring 0 -- full access to all privileged instructions, registers, and memory and I/O areas.Worldbeater
@BenVoigt: I'm completely aware of all that; like I said earlier, I don't need a lecture on the topic, and it was never my intention to explain everything perfectly accurately in my answer. If you think all of that is necessary for someone at this stage of the learning process to know, then post it as an answer instead of a comment so the OP actually sees it and can benefit from it.Person
S
4

Your C++ program is using Qt library (also coded in C++). The Qt library will be using Windows CreateWindowEx function (which was coded in C inside kernel32.dll). Or under Linux it may be using Xlib (also coded in C), but it could as well be sending the raw bytes that in X protocol mean "Please create a window for me".

Related to your catch-22 question is the historical note that “the first C++ compiler was written in C++”, although actually it was a C compiler with a few C++ notions, enough so it could compile the first version, which could then compile itself.

Similarly, the GCC compiler uses GCC extensions: it is first compiled to a version then used to recompile itself. (GCC build instructions)

Seamark answered 28/7, 2014 at 13:24 Comment(0)
A
2

How i see the question this is actually a compiler question.

Look at it this way, you write a piece of code in Assembly(you can do it in any language) which translates your newly written language you want to call Z++ into Assembly, for simplicity lets call it a compiler (it is a compiler).

Now you give this compiler some basic functions, so that you can write int, string, arrays etc. actually you give it enough abilities so that you can write the compiler itself in Z++. and now you have a compiler for Z++ written in Z++, pretty neat right.

Whats even cooler is that now you can add abilities to that compiler using the abilities it already has, thus expanding the Z++ language with new features by using the previous features

An example, if you write enough code to draw a pixel in any color, then you can expand it using the Z++ to draw anything you want.

Appointor answered 31/7, 2014 at 11:33 Comment(0)
P
0

The hardware is what allows this to happen. You can think of the graphics memory as a large array (consisting of every pixel on the screen). To draw to the screen you can write to this memory using C++ or any language that allows direct access to that memory. That memory just happens to be accessible by or located on the graphics card.

On modern systems accessing the graphics memory directly would require writing a driver because of various restrictions so you use indirect means. Libraries that create a window (really just an image like any other image) and then write that image to the graphics memory which the GPU then displays on screen. Nothing has to be added to the language except the ability to write to specific memory locations, which is what pointers are for.

Puparium answered 31/7, 2014 at 15:41 Comment(1)
The point I was trying to make is that a language doesn't need to "expand" itself in the sense that a new version of the language needs to be rewritten, and that it isn't really circular since to do anything interesting a program must interface with the hardware.Puparium

© 2022 - 2024 — McMap. All rights reserved.