|
@@ -38,6 +38,50 @@ typedef struct {
|
38
|
38
|
*
|
39
|
39
|
*/
|
40
|
40
|
|
|
41
|
+/*
|
|
42
|
+ * Declaration of variables in .data16
|
|
43
|
+ *
|
|
44
|
+ * To place a variable in the .data16 segment, declare it using the
|
|
45
|
+ * pattern:
|
|
46
|
+ *
|
|
47
|
+ * int __data16 ( foo );
|
|
48
|
+ * #define foo __use_data16 ( foo );
|
|
49
|
+ *
|
|
50
|
+ * extern uint32_t __data16 ( bar );
|
|
51
|
+ * #define bar __use_data16 ( bar );
|
|
52
|
+ *
|
|
53
|
+ * extern long __data16 ( baz ) = 0xff000000UL;
|
|
54
|
+ * #define bar __use_data16 ( baz );
|
|
55
|
+ *
|
|
56
|
+ * i.e. take a normal declaration, add __data16() around the variable
|
|
57
|
+ * name, and add a line saying "#define <name> __use_data16 ( <name> )
|
|
58
|
+ *
|
|
59
|
+ * You can then access them just like any other variable, for example
|
|
60
|
+ *
|
|
61
|
+ * int x = foo + bar;
|
|
62
|
+ *
|
|
63
|
+ * This magic is achieved at a cost of only around 7 extra bytes per
|
|
64
|
+ * group of accesses to .data16 variables. When using KEEP_IT_REAL,
|
|
65
|
+ * there is no extra cost.
|
|
66
|
+ *
|
|
67
|
+ * You should place variables in .data16 when they need to be accessed
|
|
68
|
+ * by real-mode code. Real-mode assembly (e.g. as created by
|
|
69
|
+ * REAL_EXEC()) can access these variables via the usual data segment.
|
|
70
|
+ * You can therefore write something like
|
|
71
|
+ *
|
|
72
|
+ * static uint16_t __data16 ( foo );
|
|
73
|
+ * #define foo __use_data16 ( foo )
|
|
74
|
+ *
|
|
75
|
+ * int bar ( void ) {
|
|
76
|
+ * REAL_EXEC ( baz,
|
|
77
|
+ * "int $0xff\n\t"
|
|
78
|
+ * "movw %ax, foo",
|
|
79
|
+ * ... );
|
|
80
|
+ * return foo;
|
|
81
|
+ * }
|
|
82
|
+ *
|
|
83
|
+ */
|
|
84
|
+
|
41
|
85
|
/*
|
42
|
86
|
* void copy_to_real ( uint16_t dest_seg, uint16_t dest_off,
|
43
|
87
|
* void *src, size_t n )
|